diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 95855d1cad9f..ac99fc043e54 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -142,21 +142,8 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, unsigned long flags) { struct gb_connection *connection; - struct ida *id_map = &hd->cport_id_map; - int ida_start, ida_end; int ret; - if (hd_cport_id < 0) { - ida_start = 0; - ida_end = hd->num_cports; - } else if (hd_cport_id < hd->num_cports) { - ida_start = hd_cport_id; - ida_end = hd_cport_id + 1; - } else { - dev_err(&hd->dev, "cport %d not available\n", hd_cport_id); - return ERR_PTR(-EINVAL); - } - mutex_lock(&gb_connection_mutex); if (intf && gb_connection_intf_find(intf, cport_id)) { @@ -165,15 +152,17 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, goto err_unlock; } - ret = ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); - if (ret < 0) + ret = gb_hd_cport_allocate(hd, hd_cport_id); + if (ret < 0) { + dev_err(&hd->dev, "failed to allocate cport: %d\n", ret); goto err_unlock; + } hd_cport_id = ret; connection = kzalloc(sizeof(*connection), GFP_KERNEL); if (!connection) { ret = -ENOMEM; - goto err_remove_ida; + goto err_hd_cport_release; } connection->hd_cport_id = hd_cport_id; @@ -219,8 +208,8 @@ _gb_connection_create(struct gb_host_device *hd, int hd_cport_id, err_free_connection: kfree(connection); -err_remove_ida: - ida_simple_remove(id_map, hd_cport_id); +err_hd_cport_release: + gb_hd_cport_release(hd, hd_cport_id); err_unlock: mutex_unlock(&gb_connection_mutex); @@ -658,8 +647,6 @@ EXPORT_SYMBOL_GPL(gb_connection_disable); /* Caller must have disabled the connection before destroying it. */ void gb_connection_destroy(struct gb_connection *connection) { - struct ida *id_map; - if (!connection) return; @@ -672,8 +659,7 @@ void gb_connection_destroy(struct gb_connection *connection) destroy_workqueue(connection->wq); - id_map = &connection->hd->cport_id_map; - ida_simple_remove(id_map, connection->hd_cport_id); + gb_hd_cport_release(connection->hd, connection->hd_cport_id); connection->hd_cport_id = CPORT_ID_BAD; mutex_unlock(&gb_connection_mutex); diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c index 28634720221d..f24e06b0d697 100644 --- a/drivers/staging/greybus/hd.c +++ b/drivers/staging/greybus/hd.c @@ -39,6 +39,32 @@ static struct attribute *bus_attrs[] = { }; ATTRIBUTE_GROUPS(bus); +/* Locking: Caller guarantees serialisation */ +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id) +{ + struct ida *id_map = &hd->cport_id_map; + int ida_start, ida_end; + + if (cport_id < 0) { + ida_start = 0; + ida_end = hd->num_cports; + } else if (cport_id < hd->num_cports) { + ida_start = cport_id; + ida_end = cport_id + 1; + } else { + dev_err(&hd->dev, "cport %d not available\n", cport_id); + return -EINVAL; + } + + return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL); +} + +/* Locking: Caller guarantees serialisation */ +void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) +{ + ida_simple_remove(&hd->cport_id_map, cport_id); +} + static void gb_hd_release(struct device *dev) { struct gb_host_device *hd = to_gb_host_device(dev); diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h index ff71936a7932..4a197ac9ed80 100644 --- a/drivers/staging/greybus/hd.h +++ b/drivers/staging/greybus/hd.h @@ -50,6 +50,9 @@ struct gb_host_device { }; #define to_gb_host_device(d) container_of(d, struct gb_host_device, dev) +int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id); +void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id); + struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, struct device *parent, size_t buffer_size_max,