summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/connection.c
diff options
context:
space:
mode:
authorJohan Hovold2015-07-14 15:43:30 +0200
committerGreg Kroah-Hartman2015-07-15 21:39:13 +0200
commitcad09a8f8ce843aa11f9a6a8a7aa5c6d6591147b (patch)
treebaf0a48ef28e1bb478d688ce52572972e7b21e68 /drivers/staging/greybus/connection.c
parentgreybus: operation: suppress response submission on connection tear down (diff)
downloadkernel-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.c24
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);
/*