]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
greybus: add bg_hd_connection_find()
authorAlex Elder <elder@linaro.org>
Mon, 6 Oct 2014 11:53:08 +0000 (06:53 -0500)
committerGreg Kroah-Hartman <greg@kroah.com>
Mon, 6 Oct 2014 15:56:42 +0000 (08:56 -0700)
Add a function that looks up a connection given the host device
pointer an the host cport id.  This will be used to determine which
connection an incoming message is associated with.

Replace the list tracking host device connections with a red-black
tree so lookup can scale and be done quickly.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
drivers/staging/greybus/connection.c
drivers/staging/greybus/connection.h
drivers/staging/greybus/core.c
drivers/staging/greybus/greybus.h

index 53086126f961032d1cdd3ea208db6d7e35d064b6..449ae34bf531d6b4829871dfdef1378a207cfcb8 100644 (file)
 
 static DEFINE_SPINLOCK(gb_connections_lock);
 
+static void _gb_hd_connection_insert(struct greybus_host_device *hd,
+                                       struct gb_connection *connection)
+{
+       struct rb_root *root = &hd->connections;
+       struct rb_node *node = &connection->hd_node;
+       struct rb_node **link = &root->rb_node;
+       struct rb_node *above = NULL;
+       u16 cport_id = connection->hd_cport_id;
+
+       while (*link) {
+               struct gb_connection *connection;
+
+               above = *link;
+               connection = rb_entry(above, struct gb_connection, hd_node);
+               if (connection->hd_cport_id > cport_id)
+                       link = &above->rb_left;
+               else if (connection->hd_cport_id < cport_id)
+                       link = &above->rb_right;
+       }
+       rb_link_node(node, above, link);
+       rb_insert_color(node, root);
+}
+
+static void _gb_hd_connection_remove(struct gb_connection *connection)
+{
+       rb_erase(&connection->hd_node, &connection->hd->connections);
+}
+
+struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd,
+                                               u16 cport_id)
+{
+       struct gb_connection *connection = NULL;
+       struct rb_node *node;
+
+       spin_lock_irq(&gb_connections_lock);
+       node = hd->connections.rb_node;
+       while (node) {
+               connection = rb_entry(node, struct gb_connection, hd_node);
+               if (connection->hd_cport_id > cport_id)
+                       node = node->rb_left;
+               else if (connection->hd_cport_id < cport_id)
+                       node = node->rb_right;
+               else
+                       break;
+       }
+       spin_unlock_irq(&gb_connections_lock);
+
+       return connection;
+}
+
 /*
  * Allocate an available CPort Id for use for the host side of the
  * given connection.  The lowest-available id is returned, so the
@@ -80,7 +130,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
        connection->protocol = protocol;
 
        spin_lock_irq(&gb_connections_lock);
-       list_add_tail(&connection->hd_links, &hd->connections);
+       _gb_hd_connection_insert(hd, connection);
        list_add_tail(&connection->interface_links, &interface->connections);
        spin_unlock_irq(&gb_connections_lock);
 
@@ -102,8 +152,8 @@ void gb_connection_destroy(struct gb_connection *connection)
        WARN_ON(!list_empty(&connection->operations));
 
        spin_lock_irq(&gb_connections_lock);
-       list_del(&connection->hd_links);
        list_del(&connection->interface_links);
+       _gb_hd_connection_remove(connection);
        spin_unlock_irq(&gb_connections_lock);
 
        gb_connection_hd_cport_id_free(connection);
index 61e94357db3ad5ebaceb17cb988c944a38715802..89d58e5707bc7c52912f0f93bdc0e2b04ae054a7 100644 (file)
@@ -19,7 +19,7 @@ struct gb_connection {
        u16                             hd_cport_id;
        u16                             interface_cport_id;
 
-       struct list_head                hd_links;
+       struct rb_node                  hd_node;
        struct list_head                interface_links;
        enum greybus_protocol           protocol;
 
@@ -33,6 +33,9 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
                                u16 cport_id, enum greybus_protocol protocol);
 void gb_connection_destroy(struct gb_connection *connection);
 
+struct gb_connection *gb_hd_connection_find(struct greybus_host_device *hd,
+                               u16 cport_id);
+
 u16 gb_connection_op_id(struct gb_connection *connection);
 
 __printf(2, 3)
index 41fb7caf0d8ba9e47c2addddb88a52dff1d24f48..51d7e59362d503e94d4af24aaac5a967517a25e1 100644 (file)
@@ -311,7 +311,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
        hd->parent = parent;
        hd->driver = driver;
        INIT_LIST_HEAD(&hd->modules);
-       INIT_LIST_HEAD(&hd->connections);
+       hd->connections = RB_ROOT;
        ida_init(&hd->cport_id_map);
 
        return hd;
index f4ca18aba2a679a7929095b6966b5fea71b13863..ae7d32244c53e90b6d4eea6f960cb4d185199dea 100644 (file)
@@ -187,7 +187,7 @@ struct greybus_host_device {
        const struct greybus_host_driver *driver;
 
        struct list_head modules;
-       struct list_head connections;
+       struct rb_root connections;
        struct ida cport_id_map;
 
        /* Private data for the host driver */