greybus: interface: separate disabling from removal
authorJohan Hovold <johan@hovoldconsulting.com>
Wed, 9 Mar 2016 11:20:43 +0000 (12:20 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 10 Mar 2016 21:57:42 +0000 (13:57 -0800)
Separate interface disable from interface removal.

Disabling an interface means tearing down its control connection and
destroying (i.e. deregistering and releasing) its bundles, while
removing it means deregistering and releasing the interface itself.

This is needed to implement controlled module removal, where the module
interfaces are disabled before being physically ejected.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Jeffrey Carlyle <jcarlyle@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/interface.c
drivers/staging/greybus/interface.h
drivers/staging/greybus/svc.c

index 072e7c5a72e6e7adb8657b4513aba556e4b97527..44226c4c48ec5175e86dd775fee4195009913cfe 100644 (file)
@@ -137,36 +137,6 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd,
        return intf;
 }
 
-/*
- * Tear down a previously set up interface.
- */
-void gb_interface_remove(struct gb_interface *intf)
-{
-       struct gb_bundle *bundle;
-       struct gb_bundle *next;
-
-       /*
-        * Disable the control-connection early to avoid operation timeouts
-        * when the interface is already gone.
-        */
-       if (intf->disconnected)
-               gb_control_disable(intf->control);
-
-       list_for_each_entry_safe(bundle, next, &intf->bundles, links)
-               gb_bundle_destroy(bundle);
-
-       if (device_is_registered(&intf->dev)) {
-               device_del(&intf->dev);
-               dev_info(&intf->dev, "Interface removed\n");
-       }
-
-       gb_control_disable(intf->control);
-
-       list_del(&intf->links);
-
-       put_device(&intf->dev);
-}
-
 /*
  * Enable an interface by enabling its control connection and fetching the
  * manifest and other information over it.
@@ -241,6 +211,25 @@ err_disable_control:
        return ret;
 }
 
+/* Disable an interface and destroy its bundles. */
+void gb_interface_disable(struct gb_interface *intf)
+{
+       struct gb_bundle *bundle;
+       struct gb_bundle *next;
+
+       /*
+        * Disable the control-connection early to avoid operation timeouts
+        * when the interface is already gone.
+        */
+       if (intf->disconnected)
+               gb_control_disable(intf->control);
+
+       list_for_each_entry_safe(bundle, next, &intf->bundles, links)
+               gb_bundle_destroy(bundle);
+
+       gb_control_disable(intf->control);
+}
+
 /* Register an interface and its bundles. */
 int gb_interface_add(struct gb_interface *intf)
 {
@@ -268,3 +257,16 @@ int gb_interface_add(struct gb_interface *intf)
 
        return 0;
 }
+
+/* Deregister an interface and drop its reference. */
+void gb_interface_remove(struct gb_interface *intf)
+{
+       if (device_is_registered(&intf->dev)) {
+               device_del(&intf->dev);
+               dev_info(&intf->dev, "Interface removed\n");
+       }
+
+       list_del(&intf->links);
+
+       put_device(&intf->dev);
+}
index 4b69e9ee907060594cc32be07ce7de0bff9beb66..d4c55abae25820db33014cf8b69c2622a8224182 100644 (file)
@@ -48,6 +48,7 @@ struct gb_interface *gb_interface_find(struct gb_host_device *hd,
 struct gb_interface *gb_interface_create(struct gb_host_device *hd,
                                         u8 interface_id);
 int gb_interface_enable(struct gb_interface *intf);
+void gb_interface_disable(struct gb_interface *intf);
 int gb_interface_add(struct gb_interface *intf);
 void gb_interface_remove(struct gb_interface *intf);
 
index 631a76965b53773782310e8502fff45a46fc9287..480a0712018d8177dbae47d2efffffdeeb481f36 100644 (file)
@@ -533,12 +533,9 @@ static void gb_svc_intf_remove(struct gb_svc *svc, struct gb_interface *intf)
 {
        intf->disconnected = true;
 
-       get_device(&intf->dev);
-
-       gb_interface_remove(intf);
+       gb_interface_disable(intf);
        gb_svc_interface_route_destroy(svc, intf);
-
-       put_device(&intf->dev);
+       gb_interface_remove(intf);
 }
 
 static void gb_svc_process_intf_hotplug(struct gb_operation *operation)
@@ -1001,8 +998,10 @@ static void gb_svc_remove_interfaces(struct gb_svc *svc)
 {
        struct gb_interface *intf, *tmp;
 
-       list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links)
+       list_for_each_entry_safe(intf, tmp, &svc->hd->interfaces, links) {
+               gb_interface_disable(intf);
                gb_interface_remove(intf);
+       }
 }
 
 void gb_svc_del(struct gb_svc *svc)