greybus: power_supply: Break supply setup into two parts
authorViresh Kumar <viresh.kumar@linaro.org>
Fri, 12 Feb 2016 10:38:32 +0000 (16:08 +0530)
committerGreg Kroah-Hartman <gregkh@google.com>
Mon, 15 Feb 2016 22:53:43 +0000 (14:53 -0800)
This breaks the power supply setup routine into two parts, the first one
allocates all the necessary resources and the second on registers
supplies to the required frameworks.

This is required to enable only TX on the connection, until we have
allocated all the resources, otherwise the request handler might get
called for partially initialized structures.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Rui Miguel Silva <rui.silva@linaro.org>
Reviewed-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/power_supply.c

index 37bea9c0cea84f4c324b4b8c2362f5283056a231..c50b30d1a632aa69776e8c1f7d789296beaaa3f0 100644 (file)
@@ -624,31 +624,33 @@ static int gb_power_supply_config(struct gb_power_supplies *supplies, int id)
 
        ret = gb_power_supply_description_get(gbpsy);
        if (ret < 0)
-               goto out;
+               return ret;
 
        ret = gb_power_supply_prop_descriptors_get(gbpsy);
        if (ret < 0)
-               goto out;
+               return ret;
 
        /* guarantee that we have an unique name, before register */
-       ret = __gb_power_supply_set_name(gbpsy->model_name, gbpsy->name,
-                                        sizeof(gbpsy->name));
-       if (ret < 0)
-               goto out;
+       return __gb_power_supply_set_name(gbpsy->model_name, gbpsy->name,
+                                         sizeof(gbpsy->name));
+}
+
+static int gb_power_supply_enable(struct gb_power_supply *gbpsy)
+{
+       int ret;
 
        ret = gb_power_supply_register(gbpsy);
        if (ret < 0)
-               goto out;
+               return ret;
 
        gbpsy->update_interval = update_interval_init;
        INIT_DELAYED_WORK(&gbpsy->work, gb_power_supply_work);
        schedule_delayed_work(&gbpsy->work, 0);
 
-out:
-       /* if everything went fine just mark it for release code to know */
-       if (ret == 0)
-               gbpsy->registered = true;
-       return ret;
+       /* everything went fine, mark it for release code to know */
+       gbpsy->registered = true;
+
+       return 0;
 }
 
 static int gb_power_supplies_setup(struct gb_power_supplies *supplies)
@@ -685,6 +687,27 @@ out:
        return ret;
 }
 
+static int gb_power_supplies_register(struct gb_power_supplies *supplies)
+{
+       struct gb_connection *connection = supplies->connection;
+       int ret = 0;
+       int i;
+
+       mutex_lock(&supplies->supplies_lock);
+
+       for (i = 0; i < supplies->supplies_count; i++) {
+               ret = gb_power_supply_enable(&supplies->supply[i]);
+               if (ret < 0) {
+                       dev_err(&connection->bundle->dev,
+                               "Fail to enable supplies devices\n");
+                       break;
+               }
+       }
+
+       mutex_unlock(&supplies->supplies_lock);
+       return ret;
+}
+
 static int gb_power_supply_event_recv(u8 type, struct gb_operation *op)
 {
        struct gb_connection *connection = op->connection;
@@ -758,8 +781,16 @@ static int gb_power_supply_connection_init(struct gb_connection *connection)
 
        ret = gb_power_supplies_setup(supplies);
        if (ret < 0)
-               _gb_power_supplies_release(supplies);
+               goto out;
+
+       ret = gb_power_supplies_register(supplies);
+       if (ret < 0)
+               goto out;
+
+       return 0;
 
+out:
+       _gb_power_supplies_release(supplies);
        return ret;
 }