greybus: interface: retry enumeration of UniPro-only modules
authorJeffrey Carlyle <jcarlyle@google.com>
Thu, 19 May 2016 01:55:13 +0000 (18:55 -0700)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 19 May 2016 01:59:22 +0000 (18:59 -0700)
Greybus modules will sometimes fail to send the mailbox poke and
erroneously be enumerated as UniPro-only modules. The root cause for
this on the module side is not fully understand, but it seems that this
may be due to "the bootrom bug:" a known problem with the bootrom where
linkup will occasionally fail because of a race condition.

Before the new hotplug code was implemented in the firmware, the SVC
would retry enumeration of modules that did not send the mailbox poke;
this patch ports that functionality to the AP.

Signed-off-by: Jeffrey Carlyle <jcarlyle@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/interface.c
drivers/staging/greybus/module.c

index a1435e9..3b56693 100644 (file)
@@ -447,7 +447,8 @@ static int gb_interface_activate_operation(struct gb_interface *intf)
                return -ENODEV;
        case GB_SVC_INTF_TYPE_UNIPRO:
                dev_err(&intf->dev, "interface type UniPro not supported\n");
-               return -ENODEV;
+               /* FIXME: check if this is a Toshiba bridge before retrying? */
+               return -EAGAIN;
        case GB_SVC_INTF_TYPE_GREYBUS:
                break;
        default:
index 5077253..ea58954 100644 (file)
@@ -138,13 +138,32 @@ static void gb_module_register_interface(struct gb_interface *intf)
        struct gb_module *module = intf->module;
        u8 intf_id = intf->interface_id;
        int ret;
+       int retries = 3;
 
        mutex_lock(&intf->mutex);
 
-       ret = gb_interface_activate(intf);
+       while (retries--) {
+               ret = gb_interface_activate(intf);
+               if (ret != -EAGAIN)
+                       break;
+       }
        if (ret) {
                dev_err(&module->dev, "failed to activate interface %u: %d\n",
                                intf_id, ret);
+
+               /*
+                * -EAGAIN indicates that the Greybus operation
+                * interface_activate determined the remote interface to be
+                * UniPro-only.  At present, we assume a UniPro-only module
+                * to be a Greybus module that failed to send its mailbox
+                * poke.  There is some reason to believe that this is
+                * because of a bug in the ES3 bootrom.  If we exhause our
+                * retries trying to activate such an interface, convert
+                * the error code back into a "no device" error.
+                */
+               if (ret == -EAGAIN)
+                       ret = -ENODEV;
+
                gb_interface_add(intf);
                goto err_unlock;
        }