static DEFINE_SPINLOCK(gb_connections_lock);
+static DEFINE_MUTEX(gb_connection_mutex);
+
/* This is only used at initialization time; no locking is required. */
static struct gb_connection *
* A connection also maintains the state of operations sent over the
* connection.
*
+ * Serialised against concurrent create and destroy using the
+ * gb_connection_mutex.
+ *
* Return: A pointer to the new connection if successful, or NULL otherwise.
*/
static struct gb_connection *
return NULL;
}
+ mutex_lock(&gb_connection_mutex);
+
hd_cport_id = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);
if (hd_cport_id < 0)
- return NULL;
+ goto err_unlock;
connection = kzalloc(sizeof(*connection), GFP_KERNEL);
if (!connection)
spin_unlock_irq(&gb_connections_lock);
+ mutex_unlock(&gb_connection_mutex);
+
return connection;
err_free_connection:
kfree(connection);
err_remove_ida:
ida_simple_remove(id_map, hd_cport_id);
+err_unlock:
+ mutex_unlock(&gb_connection_mutex);
return NULL;
}
if (!connection)
return;
+ mutex_lock(&gb_connection_mutex);
+
spin_lock_irq(&gb_connections_lock);
list_del(&connection->bundle_links);
list_del(&connection->hd_links);
ida_simple_remove(id_map, connection->hd_cport_id);
connection->hd_cport_id = CPORT_ID_BAD;
+ mutex_unlock(&gb_connection_mutex);
+
gb_connection_put(connection);
}