greybus: svc: keep interfaces registered during mode switch
authorJohan Hovold <johan@hovoldconsulting.com>
Wed, 13 Apr 2016 17:19:08 +0000 (19:19 +0200)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 21 Apr 2016 01:09:03 +0000 (10:09 +0900)
Keep a detected interface registered until it is physically removed.
Specifically, do not re-register an interface that is switching mode.

Note that this also allows us to get rid of some nasty hacks from core.
The Ara VID/PID bootrom hack for ES2 will continue to work, but is now
mostly confined to the bootrom driver.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/interface.c
drivers/staging/greybus/svc.c

index 5c87fbc..89fe901 100644 (file)
@@ -426,8 +426,9 @@ void gb_interface_deactivate(struct gb_interface *intf)
 }
 
 /*
- * Enable an interface by enabling its control connection and fetching the
- * manifest and other information over it.
+ * Enable an interface by enabling its control connection, fetching the
+ * manifest and other information over it, and finally registering its child
+ * devices.
  */
 int gb_interface_enable(struct gb_interface *intf)
 {
@@ -499,6 +500,19 @@ int gb_interface_enable(struct gb_interface *intf)
        if (ret)
                goto err_destroy_bundles;
 
+       /* Register the control device and any bundles */
+       ret = gb_control_add(intf->control);
+       if (ret)
+               goto err_destroy_bundles;
+
+       list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) {
+               ret = gb_bundle_add(bundle);
+               if (ret) {
+                       gb_bundle_destroy(bundle);
+                       continue;
+               }
+       }
+
        kfree(manifest);
 
        intf->enabled = true;
@@ -546,10 +560,9 @@ void gb_interface_disable(struct gb_interface *intf)
        intf->enabled = false;
 }
 
-/* Register an interface and its bundles. */
+/* Register an interface. */
 int gb_interface_add(struct gb_interface *intf)
 {
-       struct gb_bundle *bundle, *tmp;
        int ret;
 
        ret = device_add(&intf->dev);
@@ -563,17 +576,6 @@ int gb_interface_add(struct gb_interface *intf)
        dev_info(&intf->dev, "DDBL1 Manufacturer=0x%08x, Product=0x%08x\n",
                 intf->ddbl1_manufacturer_id, intf->ddbl1_product_id);
 
-       /* NOTE: ignoring errors for now */
-       gb_control_add(intf->control);
-
-       list_for_each_entry_safe_reverse(bundle, tmp, &intf->bundles, links) {
-               ret = gb_bundle_add(bundle);
-               if (ret) {
-                       gb_bundle_destroy(bundle);
-                       continue;
-               }
-       }
-
        return 0;
 }
 
index 25978e7..a9ef16e 100644 (file)
@@ -452,8 +452,6 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
        struct gb_host_device *hd = connection->hd;
        struct gb_interface *intf;
        u8 intf_id;
-       u32 vendor_id = 0;
-       u32 product_id = 0;
        int ret;
 
        /* The request message size has already been verified. */
@@ -464,27 +462,15 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
 
        intf = gb_interface_find(hd, intf_id);
        if (intf) {
-               /* HACK: Save Ara VID/PID for ES2 hack below */
-               vendor_id = intf->vendor_id;
-               product_id = intf->product_id;
-
-               /*
-                * We have received a hotplug request for an interface that
-                * already exists.
-                *
-                * This can happen in cases like:
-                * - bootrom loading the firmware image and booting into that,
-                *   which only generates a hotplug event. i.e. no hot-unplug
-                *   event.
-                * - Or the firmware on the module crashed and sent hotplug
-                *   request again to the SVC, which got propagated to AP.
-                *
-                * Remove the interface and add it again, and let user know
-                * about this with a print message.
-                */
-               dev_info(&svc->dev, "removing interface %u to add it again\n",
+               dev_info(&svc->dev, "mode switch detected on interface %u\n",
                                intf_id);
-               gb_svc_intf_remove(svc, intf);
+
+               /* Mark as disconnected to prevent I/O during disable. */
+               intf->disconnected = true;
+               gb_interface_disable(intf);
+               intf->disconnected = false;
+
+               goto enable_interface;
        }
 
        intf = gb_interface_create(hd, intf_id);
@@ -498,19 +484,15 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
        if (ret) {
                dev_err(&svc->dev, "failed to activate interface %u: %d\n",
                                intf_id, ret);
-               goto err_interface_add;
+               gb_interface_add(intf);
+               return;
        }
 
-       /*
-        * HACK: Use Ara VID/PID from earlier boot stage.
-        *
-        * FIXME: remove quirk with ES2 support
-        */
-       if (intf->quirks & GB_INTERFACE_QUIRK_NO_ARA_IDS) {
-               intf->vendor_id = vendor_id;
-               intf->product_id = product_id;
-       }
+       ret = gb_interface_add(intf);
+       if (ret)
+               goto err_interface_deactivate;
 
+enable_interface:
        ret = gb_interface_enable(intf);
        if (ret) {
                dev_err(&svc->dev, "failed to enable interface %u: %d\n",
@@ -518,19 +500,10 @@ static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
                goto err_interface_deactivate;
        }
 
-       ret = gb_interface_add(intf);
-       if (ret) {
-               gb_interface_disable(intf);
-               gb_interface_deactivate(intf);
-               return;
-       }
-
        return;
 
 err_interface_deactivate:
        gb_interface_deactivate(intf);
-err_interface_add:
-       gb_interface_add(intf);
 }
 
 static void gb_svc_process_intf_hot_unplug(struct gb_operation *operation)