Commit cad09a8f authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

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: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 886c6069
...@@ -65,8 +65,13 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, ...@@ -65,8 +65,13 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct gb_connection *connection = to_gb_connection(dev); 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); static DEVICE_ATTR_RO(state);
...@@ -204,6 +209,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle, ...@@ -204,6 +209,7 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle,
spin_unlock_irq(&gb_connections_lock); spin_unlock_irq(&gb_connections_lock);
atomic_set(&connection->op_cycle, 0); atomic_set(&connection->op_cycle, 0);
spin_lock_init(&connection->lock);
INIT_LIST_HEAD(&connection->operations); INIT_LIST_HEAD(&connection->operations);
/* XXX Will have to establish connections to get version */ /* XXX Will have to establish connections to get version */
...@@ -274,10 +280,16 @@ int gb_connection_init(struct gb_connection *connection) ...@@ -274,10 +280,16 @@ int gb_connection_init(struct gb_connection *connection)
} }
/* Need to enable the connection to initialize it */ /* Need to enable the connection to initialize it */
spin_lock_irq(&connection->lock);
connection->state = GB_CONNECTION_STATE_ENABLED; connection->state = GB_CONNECTION_STATE_ENABLED;
spin_unlock_irq(&connection->lock);
ret = connection->protocol->connection_init(connection); ret = connection->protocol->connection_init(connection);
if (ret) if (ret) {
spin_lock_irq(&connection->lock);
connection->state = GB_CONNECTION_STATE_ERROR; connection->state = GB_CONNECTION_STATE_ERROR;
spin_unlock_irq(&connection->lock);
}
return ret; return ret;
} }
...@@ -291,10 +303,14 @@ void gb_connection_exit(struct gb_connection *connection) ...@@ -291,10 +303,14 @@ void gb_connection_exit(struct gb_connection *connection)
return; 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; return;
}
connection->state = GB_CONNECTION_STATE_DESTROYING; connection->state = GB_CONNECTION_STATE_DESTROYING;
spin_unlock_irq(&connection->lock);
connection->protocol->connection_exit(connection); connection->protocol->connection_exit(connection);
/* /*
......
...@@ -35,6 +35,7 @@ struct gb_connection { ...@@ -35,6 +35,7 @@ struct gb_connection {
u8 major; u8 major;
u8 minor; u8 minor;
spinlock_t lock;
enum gb_connection_state state; enum gb_connection_state state;
atomic_t op_cycle; atomic_t op_cycle;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment