mirror of https://gitee.com/openkylin/linux.git
greybus: connection: check for duplicate cport ids
Check at connection creation time for an attempt to create a connection with an interface CPort ID that's the same as one that's already been created. Define a new helper function to look for such a duplicate. The check for a duplicate is only performed at initialization time, and CPorts are initialized serially for each bundle, so there's no need to acquire the list lock for this search. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
8267616b3e
commit
f5c2be9e9b
|
@ -11,10 +11,22 @@
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(gb_connections_lock);
|
static DEFINE_SPINLOCK(gb_connections_lock);
|
||||||
|
|
||||||
|
/* This is only used at initialization time; no locking is required. */
|
||||||
|
static struct gb_connection *
|
||||||
|
gb_connection_intf_find(struct greybus_host_device *hd, u16 cport_id)
|
||||||
|
{
|
||||||
|
struct gb_connection *connection;
|
||||||
|
|
||||||
|
list_for_each_entry(connection, &hd->connections, hd_links)
|
||||||
|
if (connection->intf_cport_id == cport_id)
|
||||||
|
return connection;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static struct gb_connection *
|
static struct gb_connection *
|
||||||
gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id)
|
gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id)
|
||||||
{
|
{
|
||||||
struct gb_connection *connection = NULL;
|
struct gb_connection *connection;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&gb_connections_lock, flags);
|
spin_lock_irqsave(&gb_connections_lock, flags);
|
||||||
|
@ -22,7 +34,7 @@ gb_connection_hd_find(struct greybus_host_device *hd, u16 cport_id)
|
||||||
if (connection->hd_cport_id == cport_id)
|
if (connection->hd_cport_id == cport_id)
|
||||||
goto found;
|
goto found;
|
||||||
connection = NULL;
|
connection = NULL;
|
||||||
found:
|
found:
|
||||||
spin_unlock_irqrestore(&gb_connections_lock, flags);
|
spin_unlock_irqrestore(&gb_connections_lock, flags);
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
|
@ -159,21 +171,29 @@ struct gb_connection *gb_connection_create(struct gb_bundle *bundle,
|
||||||
u16 cport_id, u8 protocol_id)
|
u16 cport_id, u8 protocol_id)
|
||||||
{
|
{
|
||||||
struct gb_connection *connection;
|
struct gb_connection *connection;
|
||||||
struct greybus_host_device *hd;
|
struct greybus_host_device *hd = bundle->intf->hd;
|
||||||
int retval;
|
int retval;
|
||||||
u8 major = 0;
|
u8 major = 0;
|
||||||
u8 minor = 1;
|
u8 minor = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a manifest tries to reuse a cport, reject it. We
|
||||||
|
* initialize connections serially so we don't need to worry
|
||||||
|
* about holding the connection lock.
|
||||||
|
*/
|
||||||
|
if (gb_connection_intf_find(hd, cport_id)) {
|
||||||
|
pr_err("duplicate interface cport id 0x%04hx\n", cport_id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
connection = kzalloc(sizeof(*connection), GFP_KERNEL);
|
connection = kzalloc(sizeof(*connection), GFP_KERNEL);
|
||||||
if (!connection)
|
if (!connection)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
connection->hd = hd;
|
||||||
connection->protocol_id = protocol_id;
|
connection->protocol_id = protocol_id;
|
||||||
connection->major = major;
|
connection->major = major;
|
||||||
connection->minor = minor;
|
connection->minor = minor;
|
||||||
|
|
||||||
hd = bundle->intf->hd;
|
|
||||||
connection->hd = hd;
|
|
||||||
if (!gb_connection_hd_cport_id_alloc(connection)) {
|
if (!gb_connection_hd_cport_id_alloc(connection)) {
|
||||||
gb_protocol_put(connection->protocol);
|
gb_protocol_put(connection->protocol);
|
||||||
kfree(connection);
|
kfree(connection);
|
||||||
|
|
Loading…
Reference in New Issue