greybus: bootrom: Set timeout before sending AP_READY
authorViresh Kumar <viresh.kumar@linaro.org>
Fri, 22 Jul 2016 21:13:42 +0000 (14:13 -0700)
committerGreg Kroah-Hartman <gregkh@google.com>
Fri, 22 Jul 2016 22:25:18 +0000 (15:25 -0700)
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>
drivers/staging/greybus/bootrom.c

index c5b3971..7cc4d03 100644 (file)
@@ -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: