aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-07 14:04:28 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-17 16:30:02 -0400
commite5b1e2062e0535e8ffef79bb34d857e21380d101 (patch)
tree75376f4cb69f6a1cd05b323803ae6a1a8fc4db90 /drivers/usb
parent1508124d8a4e0995362d93d82e5555a74bfc998f (diff)
USB: serial: make minor allocation dynamic
This moves the allocation of minor device numbers from a static array to be dynamic, using the idr interface. This means that you could potentially get "gaps" in a minor number range for a single USB serial device with multiple ports, but all should still work properly. We remove the 'minor' field from the usb_serial structure, as it no longer makes any sense for it (use the field in the usb_serial_port structure if you really want to know this number), and take the fact that we were overloading a number in this field to determine if we had initialized the minor numbers or not, and just use a flag variable instead. Note, we still have the limitation of 255 USB to serial devices in the system, as that is all we are registering with the TTY layer at this point in time. Tested-by: Tobias Winter <tobias@linuxdingsda.de> Reviewed-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/ark3116.c2
-rw-r--r--drivers/usb/serial/console.c6
-rw-r--r--drivers/usb/serial/f81232.c2
-rw-r--r--drivers/usb/serial/io_edgeport.c2
-rw-r--r--drivers/usb/serial/io_ti.c2
-rw-r--r--drivers/usb/serial/mos7720.c2
-rw-r--r--drivers/usb/serial/mos7840.c7
-rw-r--r--drivers/usb/serial/opticon.c2
-rw-r--r--drivers/usb/serial/pl2303.c2
-rw-r--r--drivers/usb/serial/quatech2.c2
-rw-r--r--drivers/usb/serial/ssu100.c2
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c2
-rw-r--r--drivers/usb/serial/usb-serial.c123
-rw-r--r--drivers/usb/serial/usb_wwan.c2
-rw-r--r--drivers/usb/serial/whiteheat.c2
15 files changed, 73 insertions, 87 deletions
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 293a7706ba3f..bc77e955cbef 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -413,7 +413,7 @@ static int ark3116_ioctl(struct tty_struct *tty,
413 /* XXX: Some of these values are probably wrong. */ 413 /* XXX: Some of these values are probably wrong. */
414 memset(&serstruct, 0, sizeof(serstruct)); 414 memset(&serstruct, 0, sizeof(serstruct));
415 serstruct.type = PORT_16654; 415 serstruct.type = PORT_16654;
416 serstruct.line = port->serial->minor; 416 serstruct.line = port->minor;
417 serstruct.port = port->port_number; 417 serstruct.port = port->port_number;
418 serstruct.custom_divisor = 0; 418 serstruct.custom_divisor = 0;
419 serstruct.baud_base = 460800; 419 serstruct.baud_base = 460800;
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 1b811022f1a1..afb50eab2049 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -108,18 +108,18 @@ static int usb_console_setup(struct console *co, char *options)
108 * no need to check the index here: if the index is wrong, console 108 * no need to check the index here: if the index is wrong, console
109 * code won't call us 109 * code won't call us
110 */ 110 */
111 serial = usb_serial_get_by_index(co->index); 111 port = usb_serial_port_get_by_minor(co->index);
112 if (serial == NULL) { 112 if (port == NULL) {
113 /* no device is connected yet, sorry :( */ 113 /* no device is connected yet, sorry :( */
114 pr_err("No USB device connected to ttyUSB%i\n", co->index); 114 pr_err("No USB device connected to ttyUSB%i\n", co->index);
115 return -ENODEV; 115 return -ENODEV;
116 } 116 }
117 serial = port->serial;
117 118
118 retval = usb_autopm_get_interface(serial->interface); 119 retval = usb_autopm_get_interface(serial->interface);
119 if (retval) 120 if (retval)
120 goto error_get_interface; 121 goto error_get_interface;
121 122
122 port = serial->port[co->index - serial->minor];
123 tty_port_tty_set(&port->port, NULL); 123 tty_port_tty_set(&port->port, NULL);
124 124
125 info->port = port; 125 info->port = port;
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c
index 3d53039383dd..75e85cbf9e8b 100644
--- a/drivers/usb/serial/f81232.c
+++ b/drivers/usb/serial/f81232.c
@@ -294,7 +294,7 @@ static int f81232_ioctl(struct tty_struct *tty,
294 case TIOCGSERIAL: 294 case TIOCGSERIAL:
295 memset(&ser, 0, sizeof ser); 295 memset(&ser, 0, sizeof ser);
296 ser.type = PORT_16654; 296 ser.type = PORT_16654;
297 ser.line = port->serial->minor; 297 ser.line = port->minor;
298 ser.port = port->port_number; 298 ser.port = port->port_number;
299 ser.baud_base = 460800; 299 ser.baud_base = 460800;
300 300
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 0c27ff3d2e8f..dc2803b5eb09 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1569,7 +1569,7 @@ static int get_serial_info(struct edgeport_port *edge_port,
1569 memset(&tmp, 0, sizeof(tmp)); 1569 memset(&tmp, 0, sizeof(tmp));
1570 1570
1571 tmp.type = PORT_16550A; 1571 tmp.type = PORT_16550A;
1572 tmp.line = edge_port->port->serial->minor; 1572 tmp.line = edge_port->port->minor;
1573 tmp.port = edge_port->port->port_number; 1573 tmp.port = edge_port->port->port_number;
1574 tmp.irq = 0; 1574 tmp.irq = 0;
1575 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 1575 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index d32bf2b7f988..60054e72b75b 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2363,7 +2363,7 @@ static int get_serial_info(struct edgeport_port *edge_port,
2363 memset(&tmp, 0, sizeof(tmp)); 2363 memset(&tmp, 0, sizeof(tmp));
2364 2364
2365 tmp.type = PORT_16550A; 2365 tmp.type = PORT_16550A;
2366 tmp.line = edge_port->port->serial->minor; 2366 tmp.line = edge_port->port->minor;
2367 tmp.port = edge_port->port->port_number; 2367 tmp.port = edge_port->port->port_number;
2368 tmp.irq = 0; 2368 tmp.irq = 0;
2369 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 2369 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index f79ae7fe37ff..51da424327b0 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1854,7 +1854,7 @@ static int get_serial_info(struct moschip_port *mos7720_port,
1854 memset(&tmp, 0, sizeof(tmp)); 1854 memset(&tmp, 0, sizeof(tmp));
1855 1855
1856 tmp.type = PORT_16550A; 1856 tmp.type = PORT_16550A;
1857 tmp.line = mos7720_port->port->serial->minor; 1857 tmp.line = mos7720_port->port->minor;
1858 tmp.port = mos7720_port->port->port_number; 1858 tmp.port = mos7720_port->port->port_number;
1859 tmp.irq = 0; 1859 tmp.irq = 0;
1860 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 1860 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index f981b08ff32f..0a818b238508 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1057,7 +1057,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
1057 * structures were not set up at that time.) */ 1057 * structures were not set up at that time.) */
1058 1058
1059 dev_dbg(&port->dev, "port number is %d\n", port->port_number); 1059 dev_dbg(&port->dev, "port number is %d\n", port->port_number);
1060 dev_dbg(&port->dev, "minor number is %d\n", port->serial->minor); 1060 dev_dbg(&port->dev, "minor number is %d\n", port->minor);
1061 dev_dbg(&port->dev, "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); 1061 dev_dbg(&port->dev, "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress);
1062 dev_dbg(&port->dev, "BulkOut endpoint is %d\n", port->bulk_out_endpointAddress); 1062 dev_dbg(&port->dev, "BulkOut endpoint is %d\n", port->bulk_out_endpointAddress);
1063 dev_dbg(&port->dev, "Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress); 1063 dev_dbg(&port->dev, "Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress);
@@ -2068,7 +2068,7 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
2068 memset(&tmp, 0, sizeof(tmp)); 2068 memset(&tmp, 0, sizeof(tmp));
2069 2069
2070 tmp.type = PORT_16550A; 2070 tmp.type = PORT_16550A;
2071 tmp.line = mos7840_port->port->serial->minor; 2071 tmp.line = mos7840_port->port->minor;
2072 tmp.port = mos7840_port->port->port_number; 2072 tmp.port = mos7840_port->port->port_number;
2073 tmp.irq = 0; 2073 tmp.irq = 0;
2074 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 2074 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
@@ -2246,9 +2246,8 @@ static int mos7840_port_probe(struct usb_serial_port *port)
2246 * usb-serial.c:get_free_serial() and cannot therefore be used 2246 * usb-serial.c:get_free_serial() and cannot therefore be used
2247 * to index device instances */ 2247 * to index device instances */
2248 mos7840_port->port_num = pnum + 1; 2248 mos7840_port->port_num = pnum + 1;
2249 dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); 2249 dev_dbg(&port->dev, "port->minor = %d\n", port->minor);
2250 dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); 2250 dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
2251 dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor);
2252 2251
2253 if (mos7840_port->port_num == 1) { 2252 if (mos7840_port->port_num == 1) {
2254 mos7840_port->SpRegOffset = 0x0; 2253 mos7840_port->SpRegOffset = 0x0;
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index 6e1ee85e44f2..cbe779f578f9 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -348,7 +348,7 @@ static int get_serial_info(struct usb_serial_port *port,
348 348
349 /* fake emulate a 16550 uart to make userspace code happy */ 349 /* fake emulate a 16550 uart to make userspace code happy */
350 tmp.type = PORT_16550A; 350 tmp.type = PORT_16550A;
351 tmp.line = port->serial->minor; 351 tmp.line = port->minor;
352 tmp.port = 0; 352 tmp.port = 0;
353 tmp.irq = 0; 353 tmp.irq = 0;
354 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 354 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 042ae6be3cbe..cb6bbed374f2 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -639,7 +639,7 @@ static int pl2303_ioctl(struct tty_struct *tty,
639 case TIOCGSERIAL: 639 case TIOCGSERIAL:
640 memset(&ser, 0, sizeof ser); 640 memset(&ser, 0, sizeof ser);
641 ser.type = PORT_16654; 641 ser.type = PORT_16654;
642 ser.line = port->serial->minor; 642 ser.line = port->minor;
643 ser.port = port->port_number; 643 ser.port = port->port_number;
644 ser.baud_base = 460800; 644 ser.baud_base = 460800;
645 645
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index f2ca7d80c8a0..d99743290fc1 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -465,7 +465,7 @@ static int get_serial_info(struct usb_serial_port *port,
465 return -EFAULT; 465 return -EFAULT;
466 466
467 memset(&tmp, 0, sizeof(tmp)); 467 memset(&tmp, 0, sizeof(tmp));
468 tmp.line = port->serial->minor; 468 tmp.line = port->minor;
469 tmp.port = 0; 469 tmp.port = 0;
470 tmp.irq = 0; 470 tmp.irq = 0;
471 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 471 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 5b62dbbdf996..e5750be49054 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -323,7 +323,7 @@ static int get_serial_info(struct usb_serial_port *port,
323 return -EFAULT; 323 return -EFAULT;
324 324
325 memset(&tmp, 0, sizeof(tmp)); 325 memset(&tmp, 0, sizeof(tmp));
326 tmp.line = port->serial->minor; 326 tmp.line = port->minor;
327 tmp.port = 0; 327 tmp.port = 0;
328 tmp.irq = 0; 328 tmp.irq = 0;
329 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 329 tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 07e5c9bec48a..c9c46d6f8c80 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1308,7 +1308,7 @@ static int ti_get_serial_info(struct ti_port *tport,
1308 memset(&ret_serial, 0, sizeof(ret_serial)); 1308 memset(&ret_serial, 0, sizeof(ret_serial));
1309 1309
1310 ret_serial.type = PORT_16550A; 1310 ret_serial.type = PORT_16550A;
1311 ret_serial.line = port->serial->minor; 1311 ret_serial.line = port->minor;
1312 ret_serial.port = port->port_number; 1312 ret_serial.port = port->port_number;
1313 ret_serial.flags = tport->tp_flags; 1313 ret_serial.flags = tport->tp_flags;
1314 ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE; 1314 ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index a47fa715aaba..e2e131f85002 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -37,6 +37,7 @@
37#include <linux/usb.h> 37#include <linux/usb.h>
38#include <linux/usb/serial.h> 38#include <linux/usb/serial.h>
39#include <linux/kfifo.h> 39#include <linux/kfifo.h>
40#include <linux/idr.h>
40#include "pl2303.h" 41#include "pl2303.h"
41 42
42#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" 43#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
@@ -49,82 +50,75 @@
49 drivers depend on it. 50 drivers depend on it.
50*/ 51*/
51 52
52static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; 53static DEFINE_IDR(serial_minors);
53static DEFINE_MUTEX(table_lock); 54static DEFINE_MUTEX(table_lock);
54static LIST_HEAD(usb_serial_driver_list); 55static LIST_HEAD(usb_serial_driver_list);
55 56
56/* 57/*
57 * Look up the serial structure. If it is found and it hasn't been 58 * Look up the serial port structure. If it is found and it hasn't been
58 * disconnected, return with its disc_mutex held and its refcount 59 * disconnected, return with the parent usb_serial structure's disc_mutex held
59 * incremented. Otherwise return NULL. 60 * and its refcount incremented. Otherwise return NULL.
60 */ 61 */
61struct usb_serial *usb_serial_get_by_index(unsigned index) 62struct usb_serial_port *usb_serial_port_get_by_minor(unsigned minor)
62{ 63{
63 struct usb_serial *serial; 64 struct usb_serial *serial;
65 struct usb_serial_port *port;
64 66
65 mutex_lock(&table_lock); 67 mutex_lock(&table_lock);
66 serial = serial_table[index]; 68 port = idr_find(&serial_minors, minor);
67 69 if (!port)
68 if (serial) { 70 goto exit;
69 mutex_lock(&serial->disc_mutex); 71
70 if (serial->disconnected) { 72 serial = port->serial;
71 mutex_unlock(&serial->disc_mutex); 73 mutex_lock(&serial->disc_mutex);
72 serial = NULL; 74 if (serial->disconnected) {
73 } else { 75 mutex_unlock(&serial->disc_mutex);
74 kref_get(&serial->kref); 76 port = NULL;
75 } 77 } else {
78 kref_get(&serial->kref);
76 } 79 }
80exit:
77 mutex_unlock(&table_lock); 81 mutex_unlock(&table_lock);
78 return serial; 82 return port;
79} 83}
80 84
81static struct usb_serial *get_free_serial(struct usb_serial *serial, 85static int allocate_minors(struct usb_serial *serial, int num_ports)
82 int num_ports, unsigned int *minor)
83{ 86{
87 struct usb_serial_port *port;
84 unsigned int i, j; 88 unsigned int i, j;
85 int good_spot; 89 int minor;
86 90
87 dev_dbg(&serial->interface->dev, "%s %d\n", __func__, num_ports); 91 dev_dbg(&serial->interface->dev, "%s %d\n", __func__, num_ports);
88 92
89 *minor = 0;
90 mutex_lock(&table_lock); 93 mutex_lock(&table_lock);
91 for (i = 0; i < SERIAL_TTY_MINORS; ++i) { 94 for (i = 0; i < num_ports; ++i) {
92 if (serial_table[i]) 95 port = serial->port[i];
93 continue; 96 minor = idr_alloc(&serial_minors, port, 0, 0, GFP_KERNEL);
94 97 if (minor < 0)
95 good_spot = 1; 98 goto error;
96 for (j = 1; j <= num_ports-1; ++j) 99 port->minor = minor;
97 if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) { 100 port->port_number = i;
98 good_spot = 0;
99 i += j;
100 break;
101 }
102 if (good_spot == 0)
103 continue;
104
105 *minor = i;
106 j = 0;
107 dev_dbg(&serial->interface->dev, "%s - minor base = %d\n", __func__, *minor);
108 for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i, ++j) {
109 serial_table[i] = serial;
110 serial->port[j]->minor = i;
111 serial->port[j]->port_number = i - *minor;
112 }
113 mutex_unlock(&table_lock);
114 return serial;
115 } 101 }
102 serial->minors_reserved = 1;
116 mutex_unlock(&table_lock); 103 mutex_unlock(&table_lock);
117 return NULL; 104 return 0;
105error:
106 /* unwind the already allocated minors */
107 for (j = 0; j < i; ++j)
108 idr_remove(&serial_minors, serial->port[j]->minor);
109 mutex_unlock(&table_lock);
110 return minor;
118} 111}
119 112
120static void return_serial(struct usb_serial *serial) 113static void release_minors(struct usb_serial *serial)
121{ 114{
122 int i; 115 int i;
123 116
124 mutex_lock(&table_lock); 117 mutex_lock(&table_lock);
125 for (i = 0; i < serial->num_ports; ++i) 118 for (i = 0; i < serial->num_ports; ++i)
126 serial_table[serial->minor + i] = NULL; 119 idr_remove(&serial_minors, serial->port[i]->minor);
127 mutex_unlock(&table_lock); 120 mutex_unlock(&table_lock);
121 serial->minors_reserved = 0;
128} 122}
129 123
130static void destroy_serial(struct kref *kref) 124static void destroy_serial(struct kref *kref)
@@ -136,8 +130,8 @@ static void destroy_serial(struct kref *kref)
136 serial = to_usb_serial(kref); 130 serial = to_usb_serial(kref);
137 131
138 /* return the minor range that this device had */ 132 /* return the minor range that this device had */
139 if (serial->minor != SERIAL_TTY_NO_MINOR) 133 if (serial->minors_reserved)
140 return_serial(serial); 134 release_minors(serial);
141 135
142 if (serial->attached && serial->type->release) 136 if (serial->attached && serial->type->release)
143 serial->type->release(serial); 137 serial->type->release(serial);
@@ -186,13 +180,11 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
186 struct usb_serial_port *port; 180 struct usb_serial_port *port;
187 int retval = -ENODEV; 181 int retval = -ENODEV;
188 182
189 serial = usb_serial_get_by_index(idx); 183 port = usb_serial_port_get_by_minor(idx);
190 if (!serial) 184 if (!port)
191 return retval; 185 return retval;
192 186
193 port = serial->port[idx - serial->minor]; 187 serial = port->serial;
194 if (!port)
195 goto error_no_port;
196 if (!try_module_get(serial->type->driver.owner)) 188 if (!try_module_get(serial->type->driver.owner))
197 goto error_module_get; 189 goto error_module_get;
198 190
@@ -219,7 +211,6 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
219 error_get_interface: 211 error_get_interface:
220 module_put(serial->type->driver.owner); 212 module_put(serial->type->driver.owner);
221 error_module_get: 213 error_module_get:
222 error_no_port:
223 usb_serial_put(serial); 214 usb_serial_put(serial);
224 mutex_unlock(&serial->disc_mutex); 215 mutex_unlock(&serial->disc_mutex);
225 return retval; 216 return retval;
@@ -453,14 +444,16 @@ static int serial_break(struct tty_struct *tty, int break_state)
453static int serial_proc_show(struct seq_file *m, void *v) 444static int serial_proc_show(struct seq_file *m, void *v)
454{ 445{
455 struct usb_serial *serial; 446 struct usb_serial *serial;
447 struct usb_serial_port *port;
456 int i; 448 int i;
457 char tmp[40]; 449 char tmp[40];
458 450
459 seq_puts(m, "usbserinfo:1.0 driver:2.0\n"); 451 seq_puts(m, "usbserinfo:1.0 driver:2.0\n");
460 for (i = 0; i < SERIAL_TTY_MINORS; ++i) { 452 for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
461 serial = usb_serial_get_by_index(i); 453 port = usb_serial_port_get_by_minor(i);
462 if (serial == NULL) 454 if (port == NULL)
463 continue; 455 continue;
456 serial = port->serial;
464 457
465 seq_printf(m, "%d:", i); 458 seq_printf(m, "%d:", i);
466 if (serial->type->driver.owner) 459 if (serial->type->driver.owner)
@@ -472,7 +465,7 @@ static int serial_proc_show(struct seq_file *m, void *v)
472 le16_to_cpu(serial->dev->descriptor.idVendor), 465 le16_to_cpu(serial->dev->descriptor.idVendor),
473 le16_to_cpu(serial->dev->descriptor.idProduct)); 466 le16_to_cpu(serial->dev->descriptor.idProduct));
474 seq_printf(m, " num_ports:%d", serial->num_ports); 467 seq_printf(m, " num_ports:%d", serial->num_ports);
475 seq_printf(m, " port:%d", i - serial->minor + 1); 468 seq_printf(m, " port:%d", port->port_number);
476 usb_make_path(serial->dev, tmp, sizeof(tmp)); 469 usb_make_path(serial->dev, tmp, sizeof(tmp));
477 seq_printf(m, " path:%s", tmp); 470 seq_printf(m, " path:%s", tmp);
478 471
@@ -614,7 +607,7 @@ static struct usb_serial *create_serial(struct usb_device *dev,
614 serial->interface = usb_get_intf(interface); 607 serial->interface = usb_get_intf(interface);
615 kref_init(&serial->kref); 608 kref_init(&serial->kref);
616 mutex_init(&serial->disc_mutex); 609 mutex_init(&serial->disc_mutex);
617 serial->minor = SERIAL_TTY_NO_MINOR; 610 serial->minors_reserved = 0;
618 611
619 return serial; 612 return serial;
620} 613}
@@ -723,7 +716,6 @@ static int usb_serial_probe(struct usb_interface *interface,
723 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; 716 struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
724 struct usb_serial_driver *type = NULL; 717 struct usb_serial_driver *type = NULL;
725 int retval; 718 int retval;
726 unsigned int minor;
727 int buffer_size; 719 int buffer_size;
728 int i; 720 int i;
729 int j; 721 int j;
@@ -1040,11 +1032,10 @@ static int usb_serial_probe(struct usb_interface *interface,
1040 */ 1032 */
1041 serial->disconnected = 1; 1033 serial->disconnected = 1;
1042 1034
1043 if (get_free_serial(serial, num_ports, &minor) == NULL) { 1035 if (allocate_minors(serial, num_ports)) {
1044 dev_err(ddev, "No more free serial devices\n"); 1036 dev_err(ddev, "No more free serial minor numbers\n");
1045 goto probe_error; 1037 goto probe_error;
1046 } 1038 }
1047 serial->minor = minor;
1048 1039
1049 /* register all of the individual ports with the driver core */ 1040 /* register all of the individual ports with the driver core */
1050 for (i = 0; i < num_ports; ++i) { 1041 for (i = 0; i < num_ports; ++i) {
@@ -1060,7 +1051,7 @@ static int usb_serial_probe(struct usb_interface *interface,
1060 1051
1061 serial->disconnected = 0; 1052 serial->disconnected = 0;
1062 1053
1063 usb_serial_console_init(minor); 1054 usb_serial_console_init(serial->port[0]->minor);
1064exit: 1055exit:
1065 module_put(type->driver.owner); 1056 module_put(type->driver.owner);
1066 return 0; 1057 return 0;
@@ -1224,7 +1215,6 @@ static struct usb_driver usb_serial_driver = {
1224 1215
1225static int __init usb_serial_init(void) 1216static int __init usb_serial_init(void)
1226{ 1217{
1227 int i;
1228 int result; 1218 int result;
1229 1219
1230 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS); 1220 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
@@ -1232,9 +1222,6 @@ static int __init usb_serial_init(void)
1232 return -ENOMEM; 1222 return -ENOMEM;
1233 1223
1234 /* Initialize our global data */ 1224 /* Initialize our global data */
1235 for (i = 0; i < SERIAL_TTY_MINORS; ++i)
1236 serial_table[i] = NULL;
1237
1238 result = bus_register(&usb_serial_bus_type); 1225 result = bus_register(&usb_serial_bus_type);
1239 if (result) { 1226 if (result) {
1240 pr_err("%s - registering bus driver failed\n", __func__); 1227 pr_err("%s - registering bus driver failed\n", __func__);
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index eacc27dc4657..8257d30c4072 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -124,7 +124,7 @@ static int get_serial_info(struct usb_serial_port *port,
124 return -EFAULT; 124 return -EFAULT;
125 125
126 memset(&tmp, 0, sizeof(tmp)); 126 memset(&tmp, 0, sizeof(tmp));
127 tmp.line = port->serial->minor; 127 tmp.line = port->minor;
128 tmp.port = port->port_number; 128 tmp.port = port->port_number;
129 tmp.baud_base = tty_get_baud_rate(port->port.tty); 129 tmp.baud_base = tty_get_baud_rate(port->port.tty);
130 tmp.close_delay = port->port.close_delay / 10; 130 tmp.close_delay = port->port.close_delay / 10;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 7eb34cd6b579..36a7740e827c 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -461,7 +461,7 @@ static int whiteheat_ioctl(struct tty_struct *tty,
461 case TIOCGSERIAL: 461 case TIOCGSERIAL:
462 memset(&serstruct, 0, sizeof(serstruct)); 462 memset(&serstruct, 0, sizeof(serstruct));
463 serstruct.type = PORT_16654; 463 serstruct.type = PORT_16654;
464 serstruct.line = port->serial->minor; 464 serstruct.line = port->minor;
465 serstruct.port = port->port_number; 465 serstruct.port = port->port_number;
466 serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; 466 serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
467 serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo); 467 serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo);