From: Johan Hovold <jhovold@gmail.com>
To: Greg KH <greg@kroah.com>
Cc: "Tobias Winter" <tobias@linuxdingsda.de>,
"Bjørn Mork" <bjorn@mork.no>, "Rob Landley" <rob@landley.net>,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [RFC] raise the maximum number of usb-serial devices to 512
Date: Tue, 4 Jun 2013 13:04:01 +0200 [thread overview]
Message-ID: <20130604110401.GA2566@localhost> (raw)
In-Reply-To: <20130604024959.GA10697@kroah.com>
On Mon, Jun 03, 2013 at 07:49:59PM -0700, Greg KH wrote:
> On Mon, May 27, 2013 at 02:28:51PM +0200, Bjørn Mork wrote:
> > But, IMHO, a nicer approach would be to make the allocation completely
> > dynamic, using e.g. the idr subsystem. Static tables are always feel
> > like straight jackets to me, no matter how big they are :)
>
> You are right, I didn't change the code to use idr (it predates idr by
> about a decade or so), because I thought we needed the "rage" logic that
> the usb-serial minor reservation does.
>
> But I'm not so sure anymore, so here's a patch to change to use the idr
> code, and should remove all minor number limitations (well 65k is the
> limit the tty core should be setting I think.)
>
> Tobias, can you test this patch out? Note, I only compiled it, did not
> get the chance to actually run it, so it might not work at all.
I'm afraid this won't work in it's current form. Several drivers and
parts of usb-serial core still depend on the minor numbers being
consecutive for multi-port devices. There are also still references to
SERIAL_TTY_NO_MINOR (255) as well as SERIAL_TTY_MINORS that need to be
addressed.
>
> thanks,
>
> greg k-h
>
> Subject: [PATCH] usb: serial: remove minor number limitation of 255
>
>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> drivers/usb/serial/usb-serial.c | 86 +++++++++++++++++-----------------------
> 1 file changed, 38 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
> index 4753c00..74b6f08 100644
> --- 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 <gregkh@linuxfoundation.org>"
> @@ -49,7 +50,7 @@
> 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);
>
> @@ -61,59 +62,52 @@ static LIST_HEAD(usb_serial_driver_list);
> struct usb_serial *usb_serial_get_by_index(unsigned index)
> {
> struct usb_serial *serial;
> + struct usb_serial_port *port;
>
> mutex_lock(&table_lock);
> - serial = serial_table[index];
> -
> - if (serial) {
> - mutex_lock(&serial->disc_mutex);
> - if (serial->disconnected) {
> - mutex_unlock(&serial->disc_mutex);
> - serial = NULL;
> - } else {
> - kref_get(&serial->kref);
> - }
> - }
> + port = idr_find(&serial_minors, index);
> mutex_unlock(&table_lock);
> + if (!port)
> + return NULL;
> +
> + serial = port->serial;
> + kref_get(&serial->kref);
> return serial;
> }
We would still need to handle disconnect, and make sure to return with
the disc_mutex held unless disconnected.
>
> -static struct usb_serial *get_free_serial(struct usb_serial *serial,
> - int num_ports, unsigned int *minor)
> +static int get_free_port(struct usb_serial_port *port)
> {
> - unsigned int i, j;
> - int good_spot;
> -
> - dev_dbg(&serial->interface->dev, "%s %d\n", __func__, num_ports);
> + int i;
>
> - *minor = 0;
> mutex_lock(&table_lock);
> - for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
> - if (serial_table[i])
> - continue;
> + i = idr_alloc(&serial_minors, port, 0, 0, GFP_KERNEL);
> + if (i < 0)
Missing mutex unlock (as already Dave noted).
> + return -EEXIST;
> + port->number = i;
> + mutex_unlock(&table_lock);
> + return i;
> +}
>
> - 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;
> +static int get_free_serial(struct usb_serial *serial, int num_ports,
> + unsigned int *minor)
> +{
> + unsigned int i;
> + unsigned int x;
>
> - *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) {
> - serial_table[i] = serial;
> - serial->port[j++]->number = i;
> - }
> - mutex_unlock(&table_lock);
> - return serial;
> + dev_dbg(&serial->interface->dev, "%s %d\n", __func__, num_ports);
> +
> + *minor = 0xffffffff;
> + for (i = 0; i < num_ports; ++i) {
> + x = get_free_port(serial->port[i]);
> + if (x < 0)
> + goto error;
> + if (*minor == 0xffffffff)
> + *minor = x;
> }
> - mutex_unlock(&table_lock);
> - return NULL;
> + return 0;
> +error:
> + // FIXME unwind the already allocated minors
> + return -ENODEV;
> }
As mentioned above, usb-serial core and several drivers currently depend
on us returning the first minor in a consecutive range. It's mostly used
to determine the per device port index, so storing that index in the port
structure could possibly be sufficient.
>
> static void return_serial(struct usb_serial *serial)
> @@ -122,7 +116,7 @@ static void return_serial(struct usb_serial *serial)
>
> 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]->number);
> mutex_unlock(&table_lock);
> }
>
> @@ -1041,7 +1035,7 @@ static int usb_serial_probe(struct usb_interface *interface,
> */
> serial->disconnected = 1;
>
> - if (get_free_serial(serial, num_ports, &minor) == NULL) {
> + if (get_free_serial(serial, num_ports, &minor)) {
> dev_err(ddev, "No more free serial devices\n");
> goto probe_error;
> }
> @@ -1225,7 +1219,6 @@ static struct usb_driver usb_serial_driver = {
>
> static int __init usb_serial_init(void)
> {
> - int i;
> int result;
>
> usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
> @@ -1233,9 +1226,6 @@ static int __init usb_serial_init(void)
> return -ENOMEM;
>
> /* Initialize our global data */
You could remove the above comment as well.
> - for (i = 0; i < SERIAL_TTY_MINORS; ++i)
> - serial_table[i] = NULL;
> -
> result = bus_register(&usb_serial_bus_type);
> if (result) {
> pr_err("%s - registering bus driver failed\n", __func__);
Thanks,
Johan
next prev parent reply other threads:[~2013-06-04 11:04 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-24 13:56 linux-3.9.3 - hit limit of 255 usb->serial devices Tobias Winter
2013-05-24 17:23 ` Greg KH
2013-05-27 9:30 ` [PATCH] Raise the maximum number of usb-serial devices to 256 Tobias Winter
2013-05-28 6:17 ` Rob Landley
[not found] ` <87obbwbo8s.fsf@nemi.mork.no>
[not found] ` <51A332E2.1090403@linuxdingsda.de>
2013-06-04 2:49 ` [RFC] raise the maximum number of usb-serial devices to 512 Greg KH
2013-06-04 2:59 ` Dave Jones
2013-06-04 16:12 ` Greg KH
2013-06-04 11:04 ` Johan Hovold [this message]
2013-06-04 16:31 ` Greg KH
2013-06-04 14:13 ` Alan Stern
2013-06-04 16:17 ` Greg KH
2013-06-04 17:27 ` Tobias Winter
2013-06-04 17:53 ` Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130604110401.GA2566@localhost \
--to=jhovold@gmail.com \
--cc=bjorn@mork.no \
--cc=greg@kroah.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=rob@landley.net \
--cc=tobias@linuxdingsda.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.