summaryrefslogtreecommitdiff
path: root/drivers/staging/greybus/bootrom.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2016-07-22 14:13:42 -0700
committerGreg Kroah-Hartman <gregkh@google.com>2016-07-22 15:25:18 -0700
commit6d9e6ffca4226007672800a6681c42cc877aab60 (patch)
tree87d9e9ceb0251067b0d00cfd9dd66a7e5eee5b08 /drivers/staging/greybus/bootrom.c
parent2d6f1c29988c0f5b51949bb674fe9dcdb923c4a6 (diff)
greybus: bootrom: Set timeout before sending AP_READY
A special race is observed in the case where the phone boots with modules attached to it. In that case, the AP processes a later FIRMWARE_SIZE request from the bootrom, before processing the response to the earlier AP_READY request. And because of that, we set the timeout from gb_bootrom_probe() after trying to cancel it from gb_bootrom_firmware_size_request(). And with that, if the firmware package isn't available for the kernel to directly read from, then we get a timeout print message like below: [ 23.669764] bootrom 1-3.3.1: Firmware file 'ara_00000126_00001001_fffe0001_ffe5001a_s2l.tftf' requested [ 24.680528] bootrom 1-3.3.1: Timed out waiting for Firmware Size Request from the Module Note that this doesn't happen if the module is inserted into the frame, after the phone is already booted. This behavior is the result of an earlier commit cdd1cb3f4943 ("operation: add completion work queue"). This perhaps happens only at boot time because the UNBOUND wq (connection->wq) gets a chance to run on other CPUs, while the BOUND wq (gb_operation_completion_wq) doesn't at that stage (24 seconds since boot). Setting the timeout before sending the AP_READY request fixes it for now. Reported-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Johan Hovold <johan@hovoldconsulting.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/bootrom.c')
-rw-r--r--drivers/staging/greybus/bootrom.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/staging/greybus/bootrom.c b/drivers/staging/greybus/bootrom.c
index c5b397145145..7cc4d034c421 100644
--- a/drivers/staging/greybus/bootrom.c
+++ b/drivers/staging/greybus/bootrom.c
@@ -450,23 +450,25 @@ static int gb_bootrom_probe(struct gb_bundle *bundle,
if (ret)
goto err_connection_disable;
+ /* Refresh timeout */
+ gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE,
+ NEXT_REQ_TIMEOUT_MS);
+
/* Tell bootrom we're ready. */
ret = gb_operation_sync(connection, GB_BOOTROM_TYPE_AP_READY, NULL, 0,
NULL, 0);
if (ret) {
dev_err(&connection->bundle->dev,
"failed to send AP READY: %d\n", ret);
- goto err_connection_disable;
+ goto err_cancel_timeout;
}
- /* Refresh timeout */
- gb_bootrom_set_timeout(bootrom, NEXT_REQ_FIRMWARE_SIZE,
- NEXT_REQ_TIMEOUT_MS);
-
dev_dbg(&bundle->dev, "AP_READY sent\n");
return 0;
+err_cancel_timeout:
+ cancel_delayed_work_sync(&bootrom->dwork);
err_connection_disable:
gb_connection_disable(connection);
err_connection_destroy: