aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/serial.c
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-12-23 15:10:06 -0500
committerFelipe Balbi <balbi@ti.com>2013-01-21 13:52:43 -0500
commit19b10a8828a6cdd5a4e7e37babd5084d35641f87 (patch)
tree636a228ed32d975a8214639b17b4d7a595fdf7b4 /drivers/usb/gadget/serial.c
parentb473577854fea63055ff9ab84f0f52a3e8aed15e (diff)
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 <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/serial.c')
-rw-r--r--drivers/usb/gadget/serial.c31
1 files changed, 23 insertions, 8 deletions
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);
127MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); 127MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
128 128
129/*-------------------------------------------------------------------------*/ 129/*-------------------------------------------------------------------------*/
130static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
130 131
131static int __init serial_bind_acm_config(struct usb_configuration *c) 132static int __init serial_bind_acm_config(struct usb_configuration *c)
132{ 133{
@@ -134,7 +135,7 @@ static int __init serial_bind_acm_config(struct usb_configuration *c)
134 int status = 0; 135 int status = 0;
135 136
136 for (i = 0; i < n_ports && status == 0; i++) 137 for (i = 0; i < n_ports && status == 0; i++)
137 status = acm_bind_config(c, i); 138 status = acm_bind_config(c, tty_lines[i]);
138 return status; 139 return status;
139} 140}
140 141
@@ -144,7 +145,7 @@ static int __init serial_bind_obex_config(struct usb_configuration *c)
144 int status = 0; 145 int status = 0;
145 146
146 for (i = 0; i < n_ports && status == 0; i++) 147 for (i = 0; i < n_ports && status == 0; i++)
147 status = obex_bind_config(c, i); 148 status = obex_bind_config(c, tty_lines[i]);
148 return status; 149 return status;
149} 150}
150 151
@@ -154,7 +155,7 @@ static int __init serial_bind_gser_config(struct usb_configuration *c)
154 int status = 0; 155 int status = 0;
155 156
156 for (i = 0; i < n_ports && status == 0; i++) 157 for (i = 0; i < n_ports && status == 0; i++)
157 status = gser_bind_config(c, i); 158 status = gser_bind_config(c, tty_lines[i]);
158 return status; 159 return status;
159} 160}
160 161
@@ -165,13 +166,25 @@ static struct usb_configuration serial_config_driver = {
165 .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 166 .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
166}; 167};
167 168
169static int gs_unbind(struct usb_composite_dev *cdev)
170{
171 int i;
172
173 for (i = 0; i < n_ports; i++)
174 gserial_free_line(tty_lines[i]);
175 return 0;
176}
177
168static int __init gs_bind(struct usb_composite_dev *cdev) 178static int __init gs_bind(struct usb_composite_dev *cdev)
169{ 179{
170 int status; 180 int status;
181 int cur_line;
171 182
172 status = gserial_setup(cdev->gadget, n_ports); 183 for (cur_line = 0; cur_line < n_ports; cur_line++) {
173 if (status < 0) 184 status = gserial_alloc_line(&tty_lines[cur_line]);
174 return status; 185 if (status)
186 goto fail;
187 }
175 188
176 /* Allocate string descriptor numbers ... note that string 189 /* Allocate string descriptor numbers ... note that string
177 * contents can be overridden by the composite_dev glue. 190 * contents can be overridden by the composite_dev glue.
@@ -209,7 +222,9 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
209 return 0; 222 return 0;
210 223
211fail: 224fail:
212 gserial_cleanup(); 225 cur_line--;
226 while (cur_line >= 0)
227 gserial_free_line(tty_lines[cur_line--]);
213 return status; 228 return status;
214} 229}
215 230
@@ -219,6 +234,7 @@ static __refdata struct usb_composite_driver gserial_driver = {
219 .strings = dev_strings, 234 .strings = dev_strings,
220 .max_speed = USB_SPEED_SUPER, 235 .max_speed = USB_SPEED_SUPER,
221 .bind = gs_bind, 236 .bind = gs_bind,
237 .unbind = gs_unbind,
222}; 238};
223 239
224static int __init init(void) 240static int __init init(void)
@@ -254,6 +270,5 @@ module_init(init);
254static void __exit cleanup(void) 270static void __exit cleanup(void)
255{ 271{
256 usb_composite_unregister(&gserial_driver); 272 usb_composite_unregister(&gserial_driver);
257 gserial_cleanup();
258} 273}
259module_exit(cleanup); 274module_exit(cleanup);