summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/connection.c
diff options
context:
space:
mode:
authorAlex Elder2014-10-03 21:14:24 +0200
committerGreg Kroah-Hartman2014-10-04 04:00:10 +0200
commit177404bd20fdabd77d04ad818d56ab34150fff4c (patch)
tree75d760db3a22d8b2bb2c32726a7d752bbe2a8a87 /drivers/staging/greybus/connection.c
parentgreybus: fix greybus_class_type symbol names (diff)
downloadkernel-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.c40
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);