diff options
author | Alex Elder | 2014-10-03 21:14:24 +0200 |
---|---|---|
committer | Greg Kroah-Hartman | 2014-10-04 04:00:10 +0200 |
commit | 177404bd20fdabd77d04ad818d56ab34150fff4c (patch) | |
tree | 75d760db3a22d8b2bb2c32726a7d752bbe2a8a87 /drivers/staging/greybus/connection.c | |
parent | greybus: fix greybus_class_type symbol names (diff) | |
download | kernel-qcow2-linux-177404bd20fdabd77d04ad818d56ab34150fff4c.tar.gz kernel-qcow2-linux-177404bd20fdabd77d04ad818d56ab34150fff4c.tar.xz kernel-qcow2-linux-177404bd20fdabd77d04ad818d56ab34150fff4c.zip |
greybus: use ida for cport id allocation
The ida mechanism for allocating ids may be overkill but it works.
Don't preallocate the id 0 for control. That should be done
when initializing connections based on the manifest anyway.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
Diffstat (limited to 'drivers/staging/greybus/connection.c')
-rw-r--r-- | drivers/staging/greybus/connection.c | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 806eb8cd73e0..c50472d07831 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -14,6 +14,39 @@ static DEFINE_SPINLOCK(gb_connections_lock); /* + * Allocate an available CPort Id for use for the host side of the + * given connection. The lowest-available id is returned, so the + * first call is guaranteed to allocate CPort Id 0. + * + * Assigns the connection's hd_cport_id and returns true if successful. + * Returns false otherwise. + */ +static bool hd_connection_hd_cport_id_alloc(struct gb_connection *connection) +{ + struct ida *ida = &connection->hd->cport_id_map; + int id; + + id = ida_simple_get(ida, 0, HOST_DEV_CPORT_ID_MAX, GFP_KERNEL); + if (id < 0) + return false; + + connection->hd_cport_id = (u16)id; + + return true; +} + +/* + * Free a previously-allocated CPort Id on the given host device. + */ +static void hd_connection_hd_cport_id_free(struct gb_connection *connection) +{ + struct ida *ida = &connection->hd->cport_id_map; + + ida_simple_remove(ida, connection->hd_cport_id); + connection->hd_cport_id = CPORT_ID_BAD; +} + +/* * Set up a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on * another Greybus module. @@ -35,8 +68,9 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, return NULL; hd = interface->gmod->hd; - connection->hd_cport_id = greybus_hd_cport_id_alloc(hd); - if (connection->hd_cport_id == CPORT_ID_BAD) { + connection->hd = hd; /* XXX refcount? */ + if (!hd_connection_hd_cport_id_alloc(connection)) { + /* kref_put(connection->hd); */ kfree(connection); return NULL; } @@ -72,7 +106,7 @@ void gb_connection_destroy(struct gb_connection *connection) list_del(&connection->interface_links); spin_unlock_irq(&gb_connections_lock); - greybus_hd_cport_id_free(connection->hd, connection->hd_cport_id); + hd_connection_hd_cport_id_free(connection); /* kref_put(connection->interface); */ /* kref_put(connection->hd); */ kfree(connection); |