greybus: interface: reduce control-device lifetime
authorJohan Hovold <johan@hovoldconsulting.com>
Wed, 13 Apr 2016 17:19:06 +0000 (19:19 +0200)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 21 Apr 2016 01:09:03 +0000 (10:09 +0900)
Make the control-device lifetime coincide with when the interface is
enabled (enumerated).

This is needed to be able register a new control device after a mode
switch.

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/interface.h

index f627112..5c87fbc 100644 (file)
@@ -352,9 +352,6 @@ static void gb_interface_release(struct device *dev)
 {
        struct gb_interface *intf = to_gb_interface(dev);
 
-       if (intf->control)
-               gb_control_put(intf->control);
-
        kfree(intf);
 }
 
@@ -381,7 +378,6 @@ struct device_type greybus_interface_type = {
 struct gb_interface *gb_interface_create(struct gb_host_device *hd,
                                         u8 interface_id)
 {
-       struct gb_control *control;
        struct gb_interface *intf;
 
        intf = kzalloc(sizeof(*intf), GFP_KERNEL);
@@ -404,13 +400,6 @@ struct gb_interface *gb_interface_create(struct gb_host_device *hd,
        device_initialize(&intf->dev);
        dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id);
 
-       control = gb_control_create(intf);
-       if (IS_ERR(control)) {
-               put_device(&intf->dev);
-               return NULL;
-       }
-       intf->control = control;
-
        list_add(&intf->links, &hd->interfaces);
 
        return intf;
@@ -442,6 +431,7 @@ void gb_interface_deactivate(struct gb_interface *intf)
  */
 int gb_interface_enable(struct gb_interface *intf)
 {
+       struct gb_control *control;
        struct gb_bundle *bundle, *tmp;
        int ret, size;
        void *manifest;
@@ -453,9 +443,17 @@ int gb_interface_enable(struct gb_interface *intf)
        }
 
        /* Establish control connection */
+       control = gb_control_create(intf);
+       if (IS_ERR(control)) {
+               dev_err(&intf->dev, "failed to create control device: %lu\n",
+                               PTR_ERR(control));
+               return PTR_ERR(control);
+       }
+       intf->control = control;
+
        ret = gb_control_enable(intf->control);
        if (ret)
-               return ret;
+               goto err_put_control;
 
        /* Get manifest size using control protocol on CPort */
        size = gb_control_get_manifest_size_operation(intf);
@@ -503,6 +501,8 @@ int gb_interface_enable(struct gb_interface *intf)
 
        kfree(manifest);
 
+       intf->enabled = true;
+
        return 0;
 
 err_destroy_bundles:
@@ -512,6 +512,9 @@ err_free_manifest:
        kfree(manifest);
 err_disable_control:
        gb_control_disable(intf->control);
+err_put_control:
+       gb_control_put(intf->control);
+       intf->control = NULL;
 
        return ret;
 }
@@ -522,6 +525,9 @@ void gb_interface_disable(struct gb_interface *intf)
        struct gb_bundle *bundle;
        struct gb_bundle *next;
 
+       if (!intf->enabled)
+               return;
+
        /*
         * Disable the control-connection early to avoid operation timeouts
         * when the interface is already gone.
@@ -534,6 +540,10 @@ void gb_interface_disable(struct gb_interface *intf)
 
        gb_control_del(intf->control);
        gb_control_disable(intf->control);
+       gb_control_put(intf->control);
+       intf->control = NULL;
+
+       intf->enabled = false;
 }
 
 /* Register an interface and its bundles. */
index 567b6c8..63ba696 100644 (file)
@@ -39,6 +39,7 @@ struct gb_interface {
        unsigned long quirks;
 
        bool disconnected;
+       bool enabled;
 };
 #define to_gb_interface(d) container_of(d, struct gb_interface, dev)