diff options
author | Johan Hovold | 2015-07-14 15:43:30 +0200 |
---|---|---|
committer | Greg Kroah-Hartman | 2015-07-15 21:39:13 +0200 |
commit | cad09a8f8ce843aa11f9a6a8a7aa5c6d6591147b (patch) | |
tree | baf0a48ef28e1bb478d688ce52572972e7b21e68 /drivers/staging/greybus/connection.c | |
parent | greybus: operation: suppress response submission on connection tear down (diff) | |
download | kernel-qcow2-linux-cad09a8f8ce843aa11f9a6a8a7aa5c6d6591147b.tar.gz kernel-qcow2-linux-cad09a8f8ce843aa11f9a6a8a7aa5c6d6591147b.tar.xz kernel-qcow2-linux-cad09a8f8ce843aa11f9a6a8a7aa5c6d6591147b.zip |
greybus: connection: add connection-state locking
Add locking, and the implied barriers, to connection-state updates.
This will be used to fix a number of races in the operations and
connection-tear-down implementations.
Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/connection.c')
-rw-r--r-- | drivers/staging/greybus/connection.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b9f9b11b1b65..abc1f861ea28 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -65,8 +65,13 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct gb_connection *connection = to_gb_connection(dev); + enum gb_connection_state state; - return sprintf(buf, "%d\n", connection->state); + spin_lock_irq(&connection->lock); + state = connection->state; + spin_unlock_irq(&connection->lock); + + return sprintf(buf, "%d\n", state); } static DEVICE_ATTR_RO(state); @@ -204,6 +209,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, spin_unlock_irq(&gb_connections_lock); atomic_set(&connection->op_cycle, 0); + spin_lock_init(&connection->lock); INIT_LIST_HEAD(&connection->operations); /* XXX Will have to establish connections to get version */ @@ -274,10 +280,16 @@ int gb_connection_init(struct gb_connection *connection) } /* Need to enable the connection to initialize it */ + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_ENABLED; + spin_unlock_irq(&connection->lock); + ret = connection->protocol->connection_init(connection); - if (ret) + if (ret) { + spin_lock_irq(&connection->lock); connection->state = GB_CONNECTION_STATE_ERROR; + spin_unlock_irq(&connection->lock); + } return ret; } @@ -291,10 +303,14 @@ void gb_connection_exit(struct gb_connection *connection) return; } - if (connection->state != GB_CONNECTION_STATE_ENABLED) + spin_lock_irq(&connection->lock); + if (connection->state != GB_CONNECTION_STATE_ENABLED) { + spin_unlock_irq(&connection->lock); return; - + } connection->state = GB_CONNECTION_STATE_DESTROYING; + spin_unlock_irq(&connection->lock); + connection->protocol->connection_exit(connection); /* |