Re: [PATCH v3 2/3] USB: serial: make minor allocation dynamic
@@ -123,8 +116,9 @@ static void return_serial(struct usb_ser mutex_lock(table_lock); for (i = 0; i serial-num_ports; ++i) - serial_table[serial-minor + i] = NULL; + idr_remove(serial_minors, serial-port[i]-minor); mutex_unlock(table_lock); + serial-minors_reserved = 0; This isn't strictly needed as the serial struct release_serial is only called once when the struct is about to be freed. Really? Why were we doing this type of thing before with the not allocated flag? It seems that we were protecting some path that I can't remember at the moment. So to be safe, I'll leave it for now... It was and is only used when releasing the serial struct to check whether minors had been allocated or not at probe and if return_serial (release_minors) should be called. This in done in destroy_serial just before freeing the struct, so clearing the flag is redundant, but doesn't hurt anyone, I guess. ;) Johan -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/3] USB: serial: make minor allocation dynamic
On Sat, Jun 08, 2013 at 12:03:47PM +0200, Johan Hovold wrote: On Fri, Jun 07, 2013 at 11:04:28AM -0700, Greg KH wrote: From: Greg Kroah-Hartman gre...@linuxfoundation.org Changes v2 - v3: - fixed up comments about usb_serial_get_by_minor() - fixed error case in usb_serial_get_by_minor() - folded get_free_port() into get_free_serial() - renamed get_free_serial() to allocate_minors() - fixed console.c build breakage - properly pass in minor port number to usb_serial_console_init() --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -37,6 +37,7 @@ #include linux/usb.h #include linux/usb/serial.h #include linux/kfifo.h +#include linux/idr.h #include pl2303.h #define DRIVER_AUTHOR Greg Kroah-Hartman gre...@linuxfoundation.org @@ -49,72 +50,64 @@ drivers depend on it. */ -static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; +static DEFINE_IDR(serial_minors); static DEFINE_MUTEX(table_lock); static LIST_HEAD(usb_serial_driver_list); /* - * Look up the serial structure. If it is found and it hasn't been - * disconnected, return with its disc_mutex held and its refcount - * incremented. Otherwise return NULL. + * Look up the serial port structure. If it is found and it hasn't been + * disconnected, return with the parent usb_serial structure's disc_mutex held + * and its refcount incremented. Otherwise return NULL. */ -struct usb_serial *usb_serial_get_by_index(unsigned index) +struct usb_serial_port *usb_serial_port_get_by_minor(unsigned minor) { - struct usb_serial *serial; + struct usb_serial *serial = NULL; This isn't necessary anymore. Now fixed, thanks. static void return_serial(struct usb_serial *serial) Perhaps rename this one release_minors to match allocate_minors (much better name btw)? Good idea, now done. @@ -123,8 +116,9 @@ static void return_serial(struct usb_ser mutex_lock(table_lock); for (i = 0; i serial-num_ports; ++i) - serial_table[serial-minor + i] = NULL; + idr_remove(serial_minors, serial-port[i]-minor); mutex_unlock(table_lock); + serial-minors_reserved = 0; This isn't strictly needed as the serial struct release_serial is only called once when the struct is about to be freed. Really? Why were we doing this type of thing before with the not allocated flag? It seems that we were protecting some path that I can't remember at the moment. So to be safe, I'll leave it for now... All three patches look good otherwise. The port-number disambiguation was indeed long overdue. Feel free to add Reviewed-by: Johan Hovold jhov...@gmail.com Thanks so much for the review, I'll go make these changes and apply them now. greg k-h -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/3] USB: serial: make minor allocation dynamic
On Fri, Jun 07, 2013 at 11:04:28AM -0700, Greg KH wrote: From: Greg Kroah-Hartman gre...@linuxfoundation.org Changes v2 - v3: - fixed up comments about usb_serial_get_by_minor() - fixed error case in usb_serial_get_by_minor() - folded get_free_port() into get_free_serial() - renamed get_free_serial() to allocate_minors() - fixed console.c build breakage - properly pass in minor port number to usb_serial_console_init() --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -37,6 +37,7 @@ #include linux/usb.h #include linux/usb/serial.h #include linux/kfifo.h +#include linux/idr.h #include pl2303.h #define DRIVER_AUTHOR Greg Kroah-Hartman gre...@linuxfoundation.org @@ -49,72 +50,64 @@ drivers depend on it. */ -static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; +static DEFINE_IDR(serial_minors); static DEFINE_MUTEX(table_lock); static LIST_HEAD(usb_serial_driver_list); /* - * Look up the serial structure. If it is found and it hasn't been - * disconnected, return with its disc_mutex held and its refcount - * incremented. Otherwise return NULL. + * Look up the serial port structure. If it is found and it hasn't been + * disconnected, return with the parent usb_serial structure's disc_mutex held + * and its refcount incremented. Otherwise return NULL. */ -struct usb_serial *usb_serial_get_by_index(unsigned index) +struct usb_serial_port *usb_serial_port_get_by_minor(unsigned minor) { - struct usb_serial *serial; + struct usb_serial *serial = NULL; This isn't necessary anymore. + struct usb_serial_port *port; mutex_lock(table_lock); - serial = serial_table[index]; + port = idr_find(serial_minors, minor); + if (!port) + goto exit; - if (serial) { - mutex_lock(serial-disc_mutex); - if (serial-disconnected) { - mutex_unlock(serial-disc_mutex); - serial = NULL; - } else { - kref_get(serial-kref); - } + serial = port-serial; + mutex_lock(serial-disc_mutex); + if (serial-disconnected) { + mutex_unlock(serial-disc_mutex); + port = NULL; + } else { + kref_get(serial-kref); } +exit: mutex_unlock(table_lock); - return serial; + return port; } -static struct usb_serial *get_free_serial(struct usb_serial *serial, - int num_ports, unsigned int *minor) +static int allocate_minors(struct usb_serial *serial, int num_ports) { + struct usb_serial_port *port; unsigned int i, j; - int good_spot; + int minor; dev_dbg(serial-interface-dev, %s %d\n, __func__, num_ports); - *minor = 0; mutex_lock(table_lock); - for (i = 0; i SERIAL_TTY_MINORS; ++i) { - if (serial_table[i]) - continue; - - good_spot = 1; - for (j = 1; j = num_ports-1; ++j) - if ((i+j = SERIAL_TTY_MINORS) || (serial_table[i+j])) { - good_spot = 0; - i += j; - break; - } - if (good_spot == 0) - continue; - - *minor = i; - j = 0; - dev_dbg(serial-interface-dev, %s - minor base = %d\n, __func__, *minor); - for (i = *minor; (i (*minor + num_ports)) (i SERIAL_TTY_MINORS); ++i, ++j) { - serial_table[i] = serial; - serial-port[j]-minor = i; - serial-port[j]-port_number = i - *minor; - } - mutex_unlock(table_lock); - return serial; + for (i = 0; i num_ports; ++i) { + port = serial-port[i]; + minor = idr_alloc(serial_minors, port, 0, 0, GFP_KERNEL); + if (minor 0) + goto error; + port-minor = minor; + port-port_number = i; } + serial-minors_reserved = 1; mutex_unlock(table_lock); - return NULL; + return 0; +error: + /* unwind the already allocated minors */ + for (j = 0; j i; ++j) + idr_remove(serial_minors, serial-port[j]-minor); + mutex_unlock(table_lock); + return minor; } static void return_serial(struct usb_serial *serial) Perhaps rename this one release_minors to match allocate_minors (much better name btw)? @@ -123,8 +116,9 @@ static void return_serial(struct usb_ser mutex_lock(table_lock); for (i = 0; i serial-num_ports; ++i) - serial_table[serial-minor + i] = NULL; + idr_remove(serial_minors, serial-port[i]-minor); mutex_unlock(table_lock); + serial-minors_reserved = 0; This isn't strictly needed as the
[PATCH v3 2/3] USB: serial: make minor allocation dynamic
From: Greg Kroah-Hartman gre...@linuxfoundation.org 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. Signed-off-by: Greg Kroah-Hartman gre...@linuxfoundation.org --- Changes v2 - v3: - fixed up comments about usb_serial_get_by_minor() - fixed error case in usb_serial_get_by_minor() - folded get_free_port() into get_free_serial() - renamed get_free_serial() to allocate_minors() - fixed console.c build breakage - properly pass in minor port number to usb_serial_console_init() drivers/staging/serqt_usb2/serqt_usb2.c | 15 +--- drivers/usb/serial/ark3116.c|2 drivers/usb/serial/console.c|6 - drivers/usb/serial/f81232.c |2 drivers/usb/serial/io_edgeport.c|2 drivers/usb/serial/io_ti.c |2 drivers/usb/serial/mos7720.c|2 drivers/usb/serial/mos7840.c|7 - drivers/usb/serial/opticon.c|2 drivers/usb/serial/pl2303.c |2 drivers/usb/serial/quatech2.c |2 drivers/usb/serial/ssu100.c |2 drivers/usb/serial/ti_usb_3410_5052.c |2 drivers/usb/serial/usb-serial.c | 119 ++-- drivers/usb/serial/usb_wwan.c |2 drivers/usb/serial/whiteheat.c |2 include/linux/usb/serial.h |6 - 17 files changed, 80 insertions(+), 97 deletions(-) --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -906,7 +906,7 @@ static int qt_open(struct tty_struct *tt qt_submit_urb_from_open(serial, port); } - dev_dbg(port-dev, serial number is %d\n, port-serial-minor); + dev_dbg(port-dev, minor number is %d\n, port-minor); dev_dbg(port-dev, Bulkin endpoint is %d\n, port-bulk_in_endpointAddress); dev_dbg(port-dev, @@ -1002,7 +1002,7 @@ static void qt_close(struct usb_serial_p status = 0; tty = tty_port_tty_get(port-port); - index = tty-index - serial-minor; + index = port-port_number; qt_port = qt_get_port_private(port); port0 = qt_get_port_private(serial-port[0]); @@ -1129,12 +1129,11 @@ static int qt_ioctl(struct tty_struct *t { struct usb_serial_port *port = tty-driver_data; struct quatech_port *qt_port = qt_get_port_private(port); - struct usb_serial *serial = get_usb_serial(port, __func__); unsigned int index; dev_dbg(port-dev, %s cmd 0x%04x\n, __func__, cmd); - index = tty-index - serial-minor; + index = port-port_number; if (cmd == TIOCMIWAIT) { while (qt_port != NULL) { @@ -1180,7 +1179,7 @@ static void qt_set_termios(struct tty_st int baud, divisor, remainder; int status; - index = tty-index - port-serial-minor; + index = port-port_number; switch (cflag CSIZE) { case CS5: @@ -1296,7 +1295,7 @@ static void qt_break(struct tty_struct * u16 index, onoff; unsigned int result; - index = tty-index - serial-minor; + index = port-port_number; qt_port = qt_get_port_private(port); @@ -1325,7 +1324,7 @@ static inline int qt_real_tiocmget(struc int status; unsigned int index; - index = tty-index - serial-minor; + index = port-port_number; status = BoxGetRegister(port-serial, index, MODEM_CONTROL_REGISTER, mcr); if (status = 0) { @@ -1364,7 +1363,7 @@ static inline int qt_real_tiocmset(struc int status; unsigned int index; - index = tty-index - serial-minor; + index = port-port_number; status = BoxGetRegister(port-serial, index, MODEM_CONTROL_REGISTER, mcr); if (status 0) --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -413,7 +413,7 @@ static int ark3116_ioctl(struct tty_stru /* XXX: Some of these values are probably wrong. */ memset(serstruct, 0, sizeof(serstruct)); serstruct.type = PORT_16654; - serstruct.line = port-serial-minor; + serstruct.line = port-minor; serstruct.port =