From 19b10a8828a6cdd5a4e7e37babd5084d35641f87 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 23 Dec 2012 21:10:06 +0100 Subject: usb: gadget: allocate & giveback serial ports instead hard code them This patch removes gserial_setup() and gserial_cleanup() and adds gserial_alloc_line() and gserial_free_line() to replace them. The initial setup of u_serial happens now on module load time. A maximum of four TTY ports can be requested which is the current limit. In theory we could extend this limit, the hard limit is the number of available endpoints. alloc_tty_driver() is now called at module init time with the max available ports. The per-line footprint here is on 32bit is 3 * size of pointer + 60 bytes (for cdevs). The remaining memory (struct gs_port) is allocated once a port is requested. With this change it is possible to load g_multi and g_serial at the same time. GS0 receives the module that is loaded first, GS1 is received by the next module and so on. With the configfs interface the port number can be exported and the device node is more predictable. Nothing changes for g_serial and friends as long as one module is used. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/serial.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'drivers/usb/gadget/serial.c') diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 4816f494fc4d..a883562f6a89 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -127,6 +127,7 @@ module_param(n_ports, uint, 0); MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); /*-------------------------------------------------------------------------*/ +static unsigned char tty_lines[MAX_U_SERIAL_PORTS]; static int __init serial_bind_acm_config(struct usb_configuration *c) { @@ -134,7 +135,7 @@ static int __init serial_bind_acm_config(struct usb_configuration *c) int status = 0; for (i = 0; i < n_ports && status == 0; i++) - status = acm_bind_config(c, i); + status = acm_bind_config(c, tty_lines[i]); return status; } @@ -144,7 +145,7 @@ static int __init serial_bind_obex_config(struct usb_configuration *c) int status = 0; for (i = 0; i < n_ports && status == 0; i++) - status = obex_bind_config(c, i); + status = obex_bind_config(c, tty_lines[i]); return status; } @@ -154,7 +155,7 @@ static int __init serial_bind_gser_config(struct usb_configuration *c) int status = 0; for (i = 0; i < n_ports && status == 0; i++) - status = gser_bind_config(c, i); + status = gser_bind_config(c, tty_lines[i]); return status; } @@ -165,13 +166,25 @@ static struct usb_configuration serial_config_driver = { .bmAttributes = USB_CONFIG_ATT_SELFPOWER, }; +static int gs_unbind(struct usb_composite_dev *cdev) +{ + int i; + + for (i = 0; i < n_ports; i++) + gserial_free_line(tty_lines[i]); + return 0; +} + static int __init gs_bind(struct usb_composite_dev *cdev) { int status; + int cur_line; - status = gserial_setup(cdev->gadget, n_ports); - if (status < 0) - return status; + for (cur_line = 0; cur_line < n_ports; cur_line++) { + status = gserial_alloc_line(&tty_lines[cur_line]); + if (status) + goto fail; + } /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. @@ -209,7 +222,9 @@ static int __init gs_bind(struct usb_composite_dev *cdev) return 0; fail: - gserial_cleanup(); + cur_line--; + while (cur_line >= 0) + gserial_free_line(tty_lines[cur_line--]); return status; } @@ -219,6 +234,7 @@ static __refdata struct usb_composite_driver gserial_driver = { .strings = dev_strings, .max_speed = USB_SPEED_SUPER, .bind = gs_bind, + .unbind = gs_unbind, }; static int __init init(void) @@ -254,6 +270,5 @@ module_init(init); static void __exit cleanup(void) { usb_composite_unregister(&gserial_driver); - gserial_cleanup(); } module_exit(cleanup); -- cgit v1.2.2