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

greybus: connection: serialise connection creation

Serialise connection creation against concurrent creation and
destruction using a global mutex.

This is needed to prevent two drivers from attempting to create a
connection to the same interface CPort and to cope with a racing
connection destroy when moving to driver managed connections.

Note that the locking can not (easily) be made more fine-grained as not
all connections have an interface, but these are not hot paths anyway.
Reviewed-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 0e46fab7
...@@ -16,6 +16,8 @@ static void gb_connection_kref_release(struct kref *kref); ...@@ -16,6 +16,8 @@ static void gb_connection_kref_release(struct kref *kref);
static DEFINE_SPINLOCK(gb_connections_lock); static DEFINE_SPINLOCK(gb_connections_lock);
static DEFINE_MUTEX(gb_connection_mutex);
/* This is only used at initialization time; no locking is required. */ /* This is only used at initialization time; no locking is required. */
static struct gb_connection * static struct gb_connection *
...@@ -125,6 +127,9 @@ static void gb_connection_init_name(struct gb_connection *connection) ...@@ -125,6 +127,9 @@ static void gb_connection_init_name(struct gb_connection *connection)
* A connection also maintains the state of operations sent over the * A connection also maintains the state of operations sent over the
* connection. * connection.
* *
* Serialised against concurrent create and destroy using the
* gb_connection_mutex.
*
* Return: A pointer to the new connection if successful, or NULL otherwise. * Return: A pointer to the new connection if successful, or NULL otherwise.
*/ */
static struct gb_connection * static struct gb_connection *
...@@ -159,9 +164,11 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, ...@@ -159,9 +164,11 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id,
return NULL; return NULL;
} }
mutex_lock(&gb_connection_mutex);
hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);
if (hd_cport_id < 0) if (hd_cport_id < 0)
return NULL; goto err_unlock;
connection = kzalloc(sizeof(*connection), GFP_KERNEL); connection = kzalloc(sizeof(*connection), GFP_KERNEL);
if (!connection) if (!connection)
...@@ -201,12 +208,16 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id, ...@@ -201,12 +208,16 @@ gb_connection_create(struct gb_host_device *hd, int hd_cport_id,
spin_unlock_irq(&gb_connections_lock); spin_unlock_irq(&gb_connections_lock);
mutex_unlock(&gb_connection_mutex);
return connection; return connection;
err_free_connection: err_free_connection:
kfree(connection); kfree(connection);
err_remove_ida: err_remove_ida:
ida_simple_remove(id_map, hd_cport_id); ida_simple_remove(id_map, hd_cport_id);
err_unlock:
mutex_unlock(&gb_connection_mutex);
return NULL; return NULL;
} }
...@@ -524,6 +535,8 @@ void gb_connection_destroy(struct gb_connection *connection) ...@@ -524,6 +535,8 @@ void gb_connection_destroy(struct gb_connection *connection)
if (!connection) if (!connection)
return; return;
mutex_lock(&gb_connection_mutex);
spin_lock_irq(&gb_connections_lock); spin_lock_irq(&gb_connections_lock);
list_del(&connection->bundle_links); list_del(&connection->bundle_links);
list_del(&connection->hd_links); list_del(&connection->hd_links);
...@@ -535,6 +548,8 @@ void gb_connection_destroy(struct gb_connection *connection) ...@@ -535,6 +548,8 @@ void gb_connection_destroy(struct gb_connection *connection)
ida_simple_remove(id_map, connection->hd_cport_id); ida_simple_remove(id_map, connection->hd_cport_id);
connection->hd_cport_id = CPORT_ID_BAD; connection->hd_cport_id = CPORT_ID_BAD;
mutex_unlock(&gb_connection_mutex);
gb_connection_put(connection); gb_connection_put(connection);
} }
......
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