From 5015115def3ed9907fb018180be969cf2f2f116d Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Mon, 14 Sep 2015 10:48:46 +0100 Subject: [PATCH] greybus: loopback: sort list of connections for masking purposes In user-space we specify a list of connections as a bit-mask with the assumption that a list such is indexed as indicated below. end0:3:3:1:1 = 1 end0:3:3:2:3 = 2 end0:3:3:3:4 = 4 Current code assigns bitmask ids based on the order of discovery, however user-space has no idea what the order of discovery is. This patch sorts the linked list of connections associated with the loopback driver and assigns a bit-id based on the sorted list - not the order of discovery. This change therefore enforces the end-users idea that end0:3:3:1:1 above is always denoted by bit 1 - even if from the AP's perspective it was the last entry discovered. Signed-off-by: Bryan O'Donoghue Reviewed-by: Patrick Titiano Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/loopback.c | 48 ++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index ba65457f9f70..a62e122c2bcc 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -843,6 +844,50 @@ static const struct file_operations gb_loopback_debugfs_dev_latency_ops = { .release = single_release, }; +static int gb_loopback_bus_id_compare(void *priv, struct list_head *lha, + struct list_head *lhb) +{ + struct gb_loopback *a = list_entry(lha, struct gb_loopback, entry); + struct gb_loopback *b = list_entry(lhb, struct gb_loopback, entry); + struct gb_connection *ca = a->connection; + struct gb_connection *cb = b->connection; + + if (ca->bundle->intf->module->module_id < + cb->bundle->intf->module->module_id) + return -1; + if (cb->bundle->intf->module->module_id < + ca->bundle->intf->module->module_id) + return 1; + if (ca->bundle->intf->interface_id < cb->bundle->intf->interface_id) + return -1; + if (cb->bundle->intf->interface_id < ca->bundle->intf->interface_id) + return 1; + if (ca->bundle->id < cb->bundle->id) + return -1; + if (cb->bundle->id < ca->bundle->id) + return 1; + if (ca->intf_cport_id < cb->intf_cport_id) + return -1; + else if (cb->intf_cport_id < ca->intf_cport_id) + return 1; + + return 0; +} + +static void gb_loopback_insert_id(struct gb_loopback *gb) +{ + struct gb_loopback *gb_list; + u32 new_lbid = 0; + + /* perform an insertion sort */ + list_add_tail(&gb->entry, &gb_dev.list); + list_sort(NULL, &gb_dev.list, gb_loopback_bus_id_compare); + list_for_each_entry(gb_list, &gb_dev.list, entry) { + gb_list->lbid = 1 << new_lbid; + new_lbid++; + } +} + #define DEBUGFS_NAMELEN 32 static int gb_loopback_connection_init(struct gb_connection *connection) @@ -908,14 +953,13 @@ static int gb_loopback_connection_init(struct gb_connection *connection) /* Fork worker thread */ mutex_init(&gb->mutex); - gb->lbid = 1 << gb_dev.count; gb->task = kthread_run(gb_loopback_fn, gb, "gb_loopback"); if (IS_ERR(gb->task)) { retval = PTR_ERR(gb->task); goto out_kfifo1; } - list_add_tail(&gb->entry, &gb_dev.list); + gb_loopback_insert_id(gb); gb_dev.count++; mutex_unlock(&gb_dev.mutex); return 0;