greybus: connection: make connection enable/disable thread safe
authorJohan Hovold <johan@hovoldconsulting.com>
Tue, 19 Jan 2016 11:51:06 +0000 (12:51 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Tue, 19 Jan 2016 20:12:40 +0000 (12:12 -0800)
Add connection mutex to protect connection enabling and disabling.

This is needed to eventually allow drivers to manage the state of their
connections during operation (i.e. post probe and pre disconnect).

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

index 0159fbd9d78eb3022594ffe7b0294c638c5983e1..56588f357b208658ab0d747a9c8b855b89e021ff 100644 (file)
@@ -170,6 +170,7 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id,
        connection->state = GB_CONNECTION_STATE_DISABLED;
 
        atomic_set(&connection->op_cycle, 0);
+       mutex_init(&connection->mutex);
        spin_lock_init(&connection->lock);
        INIT_LIST_HEAD(&connection->operations);
 
@@ -390,9 +391,14 @@ int gb_connection_enable(struct gb_connection *connection,
 {
        int ret;
 
+       mutex_lock(&connection->mutex);
+
+       if (connection->state == GB_CONNECTION_STATE_ENABLED)
+               goto out_unlock;
+
        ret = gb_connection_hd_cport_enable(connection);
        if (ret)
-               return ret;
+               goto err_unlock;
 
        ret = gb_connection_svc_connection_create(connection);
        if (ret)
@@ -407,6 +413,9 @@ int gb_connection_enable(struct gb_connection *connection,
        if (ret)
                goto err_svc_destroy;
 
+out_unlock:
+       mutex_unlock(&connection->mutex);
+
        return 0;
 
 err_svc_destroy:
@@ -418,6 +427,8 @@ err_svc_destroy:
        gb_connection_svc_connection_destroy(connection);
 err_hd_cport_disable:
        gb_connection_hd_cport_disable(connection);
+err_unlock:
+       mutex_unlock(&connection->mutex);
 
        return ret;
 }
@@ -425,8 +436,10 @@ EXPORT_SYMBOL_GPL(gb_connection_enable);
 
 void gb_connection_disable(struct gb_connection *connection)
 {
+       mutex_lock(&connection->mutex);
+
        if (connection->state == GB_CONNECTION_STATE_DISABLED)
-               return;
+               goto out_unlock;
 
        gb_connection_control_disconnected(connection);
 
@@ -437,6 +450,9 @@ void gb_connection_disable(struct gb_connection *connection)
 
        gb_connection_svc_connection_destroy(connection);
        gb_connection_hd_cport_disable(connection);
+
+out_unlock:
+       mutex_unlock(&connection->mutex);
 }
 EXPORT_SYMBOL_GPL(gb_connection_disable);
 
index b774b9c56744eded8b5869ee4c67461ef428fa1e..e7c6feb76e805d75b286a132960a358c1ebe4695 100644 (file)
@@ -43,6 +43,7 @@ struct gb_connection {
        u8                              module_major;
        u8                              module_minor;
 
+       struct mutex                    mutex;
        spinlock_t                      lock;
        enum gb_connection_state        state;
        struct list_head                operations;