summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2015-05-18 17:34:11 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-24 18:30:03 +0200
commit6cb4f4df686e6515f43d9fec3f43226d408999b3 (patch)
treeedf90f778d18418b2313573494b66391ffe2b5c2
parentUSB: devio: fix a condition in async_completed() (diff)
downloadlinux-6cb4f4df686e6515f43d9fec3f43226d408999b3.tar.xz
linux-6cb4f4df686e6515f43d9fec3f43226d408999b3.zip
USB: cdc-acm: use idr to manage minor numbers
Use the idr-interface rather than a static table to manage minor-number allocations. This allows us to easily switch over to fully dynamic minor allocations when the TTY-layer can handle that. Signed-off-by: Johan Hovold <johan@kernel.org> Acked-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/class/cdc-acm.c38
1 files changed, 17 insertions, 21 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 5c8f58114677..877b637e7f7b 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -46,6 +46,7 @@
#include <linux/usb/cdc.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
+#include <linux/idr.h>
#include <linux/list.h>
#include "cdc-acm.h"
@@ -56,27 +57,27 @@
static struct usb_driver acm_driver;
static struct tty_driver *acm_tty_driver;
-static struct acm *acm_table[ACM_TTY_MINORS];
-static DEFINE_MUTEX(acm_table_lock);
+static DEFINE_IDR(acm_minors);
+static DEFINE_MUTEX(acm_minors_lock);
static void acm_tty_set_termios(struct tty_struct *tty,
struct ktermios *termios_old);
/*
- * acm_table accessors
+ * acm_minors accessors
*/
/*
- * Look up an ACM structure by index. If found and not disconnected, increment
+ * Look up an ACM structure by minor. If found and not disconnected, increment
* its refcount and return it with its mutex held.
*/
-static struct acm *acm_get_by_index(unsigned index)
+static struct acm *acm_get_by_minor(unsigned int minor)
{
struct acm *acm;
- mutex_lock(&acm_table_lock);
- acm = acm_table[index];
+ mutex_lock(&acm_minors_lock);
+ acm = idr_find(&acm_minors, minor);
if (acm) {
mutex_lock(&acm->mutex);
if (acm->disconnected) {
@@ -87,7 +88,7 @@ static struct acm *acm_get_by_index(unsigned index)
mutex_unlock(&acm->mutex);
}
}
- mutex_unlock(&acm_table_lock);
+ mutex_unlock(&acm_minors_lock);
return acm;
}
@@ -98,14 +99,9 @@ static int acm_alloc_minor(struct acm *acm)
{
int minor;
- mutex_lock(&acm_table_lock);
- for (minor = 0; minor < ACM_TTY_MINORS; minor++) {
- if (!acm_table[minor]) {
- acm_table[minor] = acm;
- break;
- }
- }
- mutex_unlock(&acm_table_lock);
+ mutex_lock(&acm_minors_lock);
+ minor = idr_alloc(&acm_minors, acm, 0, ACM_TTY_MINORS, GFP_KERNEL);
+ mutex_unlock(&acm_minors_lock);
return minor;
}
@@ -113,9 +109,9 @@ static int acm_alloc_minor(struct acm *acm)
/* Release the minor number associated with 'acm'. */
static void acm_release_minor(struct acm *acm)
{
- mutex_lock(&acm_table_lock);
- acm_table[acm->minor] = NULL;
- mutex_unlock(&acm_table_lock);
+ mutex_lock(&acm_minors_lock);
+ idr_remove(&acm_minors, acm->minor);
+ mutex_unlock(&acm_minors_lock);
}
/*
@@ -497,7 +493,7 @@ static int acm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
dev_dbg(tty->dev, "%s\n", __func__);
- acm = acm_get_by_index(tty->index);
+ acm = acm_get_by_minor(tty->index);
if (!acm)
return -ENODEV;
@@ -1316,7 +1312,7 @@ made_compressed_probe:
goto alloc_fail;
minor = acm_alloc_minor(acm);
- if (minor == ACM_TTY_MINORS) {
+ if (minor < 0) {
dev_err(&intf->dev, "no more free acm devices\n");
kfree(acm);
return -ENODEV;