diff options
author | Johan Hovold <johan@kernel.org> | 2015-05-18 11:34:11 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-05-24 12:30:03 -0400 |
commit | 6cb4f4df686e6515f43d9fec3f43226d408999b3 (patch) | |
tree | edf90f778d18418b2313573494b66391ffe2b5c2 | |
parent | 83ed07c5db71bc02bd646d6eb60b48908235cdf9 (diff) |
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.c | 38 |
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 @@ | |||
46 | #include <linux/usb/cdc.h> | 46 | #include <linux/usb/cdc.h> |
47 | #include <asm/byteorder.h> | 47 | #include <asm/byteorder.h> |
48 | #include <asm/unaligned.h> | 48 | #include <asm/unaligned.h> |
49 | #include <linux/idr.h> | ||
49 | #include <linux/list.h> | 50 | #include <linux/list.h> |
50 | 51 | ||
51 | #include "cdc-acm.h" | 52 | #include "cdc-acm.h" |
@@ -56,27 +57,27 @@ | |||
56 | 57 | ||
57 | static struct usb_driver acm_driver; | 58 | static struct usb_driver acm_driver; |
58 | static struct tty_driver *acm_tty_driver; | 59 | static struct tty_driver *acm_tty_driver; |
59 | static struct acm *acm_table[ACM_TTY_MINORS]; | ||
60 | 60 | ||
61 | static DEFINE_MUTEX(acm_table_lock); | 61 | static DEFINE_IDR(acm_minors); |
62 | static DEFINE_MUTEX(acm_minors_lock); | ||
62 | 63 | ||
63 | static void acm_tty_set_termios(struct tty_struct *tty, | 64 | static void acm_tty_set_termios(struct tty_struct *tty, |
64 | struct ktermios *termios_old); | 65 | struct ktermios *termios_old); |
65 | 66 | ||
66 | /* | 67 | /* |
67 | * acm_table accessors | 68 | * acm_minors accessors |
68 | */ | 69 | */ |
69 | 70 | ||
70 | /* | 71 | /* |
71 | * Look up an ACM structure by index. If found and not disconnected, increment | 72 | * Look up an ACM structure by minor. If found and not disconnected, increment |
72 | * its refcount and return it with its mutex held. | 73 | * its refcount and return it with its mutex held. |
73 | */ | 74 | */ |
74 | static struct acm *acm_get_by_index(unsigned index) | 75 | static struct acm *acm_get_by_minor(unsigned int minor) |
75 | { | 76 | { |
76 | struct acm *acm; | 77 | struct acm *acm; |
77 | 78 | ||
78 | mutex_lock(&acm_table_lock); | 79 | mutex_lock(&acm_minors_lock); |
79 | acm = acm_table[index]; | 80 | acm = idr_find(&acm_minors, minor); |
80 | if (acm) { | 81 | if (acm) { |
81 | mutex_lock(&acm->mutex); | 82 | mutex_lock(&acm->mutex); |
82 | if (acm->disconnected) { | 83 | if (acm->disconnected) { |
@@ -87,7 +88,7 @@ static struct acm *acm_get_by_index(unsigned index) | |||
87 | mutex_unlock(&acm->mutex); | 88 | mutex_unlock(&acm->mutex); |
88 | } | 89 | } |
89 | } | 90 | } |
90 | mutex_unlock(&acm_table_lock); | 91 | mutex_unlock(&acm_minors_lock); |
91 | return acm; | 92 | return acm; |
92 | } | 93 | } |
93 | 94 | ||
@@ -98,14 +99,9 @@ static int acm_alloc_minor(struct acm *acm) | |||
98 | { | 99 | { |
99 | int minor; | 100 | int minor; |
100 | 101 | ||
101 | mutex_lock(&acm_table_lock); | 102 | mutex_lock(&acm_minors_lock); |
102 | for (minor = 0; minor < ACM_TTY_MINORS; minor++) { | 103 | minor = idr_alloc(&acm_minors, acm, 0, ACM_TTY_MINORS, GFP_KERNEL); |
103 | if (!acm_table[minor]) { | 104 | mutex_unlock(&acm_minors_lock); |
104 | acm_table[minor] = acm; | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | mutex_unlock(&acm_table_lock); | ||
109 | 105 | ||
110 | return minor; | 106 | return minor; |
111 | } | 107 | } |
@@ -113,9 +109,9 @@ static int acm_alloc_minor(struct acm *acm) | |||
113 | /* Release the minor number associated with 'acm'. */ | 109 | /* Release the minor number associated with 'acm'. */ |
114 | static void acm_release_minor(struct acm *acm) | 110 | static void acm_release_minor(struct acm *acm) |
115 | { | 111 | { |
116 | mutex_lock(&acm_table_lock); | 112 | mutex_lock(&acm_minors_lock); |
117 | acm_table[acm->minor] = NULL; | 113 | idr_remove(&acm_minors, acm->minor); |
118 | mutex_unlock(&acm_table_lock); | 114 | mutex_unlock(&acm_minors_lock); |
119 | } | 115 | } |
120 | 116 | ||
121 | /* | 117 | /* |
@@ -497,7 +493,7 @@ static int acm_tty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
497 | 493 | ||
498 | dev_dbg(tty->dev, "%s\n", __func__); | 494 | dev_dbg(tty->dev, "%s\n", __func__); |
499 | 495 | ||
500 | acm = acm_get_by_index(tty->index); | 496 | acm = acm_get_by_minor(tty->index); |
501 | if (!acm) | 497 | if (!acm) |
502 | return -ENODEV; | 498 | return -ENODEV; |
503 | 499 | ||
@@ -1316,7 +1312,7 @@ made_compressed_probe: | |||
1316 | goto alloc_fail; | 1312 | goto alloc_fail; |
1317 | 1313 | ||
1318 | minor = acm_alloc_minor(acm); | 1314 | minor = acm_alloc_minor(acm); |
1319 | if (minor == ACM_TTY_MINORS) { | 1315 | if (minor < 0) { |
1320 | dev_err(&intf->dev, "no more free acm devices\n"); | 1316 | dev_err(&intf->dev, "no more free acm devices\n"); |
1321 | kfree(acm); | 1317 | kfree(acm); |
1322 | return -ENODEV; | 1318 | return -ENODEV; |