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>
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: