aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-09-01 11:39:13 -0400
committerLive-CD User <linux@linux.site>2009-09-19 16:13:40 -0400
commitcc56cd0157753c04a987888a2f793803df661a40 (patch)
tree78397afa3711722fd859181a1228a14613e3bc8b /drivers/usb
parent8bc2c1b2daf95029658868cb1427baea2da87139 (diff)
usb-serial: acquire references when a new tty is installed
This patch (as1287) makes serial_install() be reponsible for acquiring references to the usb_serial structure and the driver module when a tty is first used. This is more sensible than having serial_open() do it, because a tty can be opened many times whereas it is installed only once, when it is created. (Not to mention that these actions are reversed when the tty is released, not when it is closed.) Finally, it is at install time that the TTY core takes its own reference to the usb_serial module, so it is only fitting that we should act the same way in regard to the lower-level serial driver. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/usb-serial.c111
1 files changed, 47 insertions, 64 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 87802ea8bbc8..7d207d91a6a8 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -187,100 +187,92 @@ void usb_serial_put(struct usb_serial *serial)
187 * Create the termios objects for this tty. We use the default 187 * Create the termios objects for this tty. We use the default
188 * USB serial settings but permit them to be overridden by 188 * USB serial settings but permit them to be overridden by
189 * serial->type->init_termios. 189 * serial->type->init_termios.
190 *
191 * This is the first place a new tty gets used. Hence this is where we
192 * acquire references to the usb_serial structure and the driver module,
193 * where we store a pointer to the port, and where we do an autoresume.
194 * All these actions are reversed in serial_do_free().
190 */ 195 */
191static int serial_install(struct tty_driver *driver, struct tty_struct *tty) 196static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
192{ 197{
193 int idx = tty->index; 198 int idx = tty->index;
194 struct usb_serial *serial; 199 struct usb_serial *serial;
195 int retval; 200 struct usb_serial_port *port;
201 int retval = -ENODEV;
202
203 serial = usb_serial_get_by_index(idx);
204 if (!serial)
205 return retval;
206
207 port = serial->port[idx - serial->minor];
208 if (!port)
209 goto error_no_port;
210 if (!try_module_get(serial->type->driver.owner))
211 goto error_module_get;
212
213 retval = usb_autopm_get_interface(serial->interface);
214 if (retval)
215 goto error_get_interface;
196 216
197 /* If the termios setup has yet to be done */ 217 /* If the termios setup has yet to be done */
198 if (tty->driver->termios[idx] == NULL) { 218 if (tty->driver->termios[idx] == NULL) {
199 /* perform the standard setup */ 219 /* perform the standard setup */
200 retval = tty_init_termios(tty); 220 retval = tty_init_termios(tty);
201 if (retval) 221 if (retval)
202 return retval; 222 goto error_init_termios;
203 /* allow the driver to update it */ 223 /* allow the driver to update it */
204 serial = usb_serial_get_by_index(tty->index); 224 if (serial->type->init_termios)
205 if (serial) { 225 serial->type->init_termios(tty);
206 if (serial->type->init_termios)
207 serial->type->init_termios(tty);
208 usb_serial_put(serial);
209 mutex_unlock(&serial->disc_mutex);
210 }
211 } 226 }
227 mutex_unlock(&serial->disc_mutex);
228
229 tty->driver_data = port;
230
212 /* Final install (we use the default method) */ 231 /* Final install (we use the default method) */
213 tty_driver_kref_get(driver); 232 tty_driver_kref_get(driver);
214 tty->count++; 233 tty->count++;
215 driver->ttys[idx] = tty; 234 driver->ttys[idx] = tty;
216 return 0; 235 return retval;
236
237 error_init_termios:
238 usb_autopm_put_interface(serial->interface);
239 error_get_interface:
240 module_put(serial->type->driver.owner);
241 error_module_get:
242 error_no_port:
243 usb_serial_put(serial);
244 mutex_unlock(&serial->disc_mutex);
245 return retval;
217} 246}
218 247
219static int serial_open (struct tty_struct *tty, struct file *filp) 248static int serial_open (struct tty_struct *tty, struct file *filp)
220{ 249{
221 struct usb_serial *serial; 250 struct usb_serial *serial;
222 struct usb_serial_port *port; 251 struct usb_serial_port *port;
223 unsigned int portNumber;
224 int retval = 0; 252 int retval = 0;
225 int first = 0; 253 int first = 0;
226 254
227 dbg("%s", __func__); 255 dbg("%s", __func__);
228 256
229 /* get the serial object associated with this tty pointer */ 257 port = tty->driver_data;
230 serial = usb_serial_get_by_index(tty->index); 258 serial = port->serial;
231 if (!serial) {
232 tty->driver_data = NULL;
233 return -ENODEV;
234 }
235
236 portNumber = tty->index - serial->minor;
237 port = serial->port[portNumber];
238 if (!port || serial->disconnected)
239 retval = -ENODEV;
240 /*
241 * Note: Our locking order requirement does not allow port->mutex
242 * to be acquired while serial->disc_mutex is held.
243 */
244 mutex_unlock(&serial->disc_mutex);
245 if (retval)
246 goto bailout_serial_put;
247 259
248 if (mutex_lock_interruptible(&port->mutex)) { 260 if (mutex_lock_interruptible(&port->mutex))
249 retval = -ERESTARTSYS; 261 return -ERESTARTSYS;
250 goto bailout_serial_put;
251 }
252 262
253 ++port->port.count; 263 ++port->port.count;
254
255 /* set up our port structure making the tty driver
256 * remember our port object, and us it */
257 tty->driver_data = port;
258 tty_port_tty_set(&port->port, tty); 264 tty_port_tty_set(&port->port, tty);
259 265
260 /* If the console is attached, the device is already open */ 266 /* If the console is attached, the device is already open */
261 if (port->port.count == 1 && !port->console) { 267 if (port->port.count == 1 && !port->console) {
262 first = 1; 268 first = 1;
263 /* lock this module before we call it
264 * this may fail, which means we must bail out,
265 * safe because we are called with BKL held */
266 if (!try_module_get(serial->type->driver.owner)) {
267 retval = -ENODEV;
268 goto bailout_mutex_unlock;
269 }
270
271 mutex_lock(&serial->disc_mutex); 269 mutex_lock(&serial->disc_mutex);
272 if (serial->disconnected)
273 retval = -ENODEV;
274 else
275 retval = usb_autopm_get_interface(serial->interface);
276 if (retval)
277 goto bailout_module_put;
278 270
279 /* only call the device specific open if this 271 /* only call the device specific open if this
280 * is the first time the port is opened */ 272 * is the first time the port is opened */
281 retval = serial->type->open(tty, port); 273 retval = serial->type->open(tty, port);
282 if (retval) 274 if (retval)
283 goto bailout_interface_put; 275 goto bailout_module_put;
284 mutex_unlock(&serial->disc_mutex); 276 mutex_unlock(&serial->disc_mutex);
285 set_bit(ASYNCB_INITIALIZED, &port->port.flags); 277 set_bit(ASYNCB_INITIALIZED, &port->port.flags);
286 } 278 }
@@ -297,18 +289,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
297 goto bailout_mutex_unlock; 289 goto bailout_mutex_unlock;
298 /* Undo the initial port actions */ 290 /* Undo the initial port actions */
299 mutex_lock(&serial->disc_mutex); 291 mutex_lock(&serial->disc_mutex);
300bailout_interface_put:
301 usb_autopm_put_interface(serial->interface);
302bailout_module_put: 292bailout_module_put:
303 mutex_unlock(&serial->disc_mutex); 293 mutex_unlock(&serial->disc_mutex);
304 module_put(serial->type->driver.owner);
305bailout_mutex_unlock: 294bailout_mutex_unlock:
306 port->port.count = 0; 295 port->port.count = 0;
307 tty->driver_data = NULL;
308 tty_port_tty_set(&port->port, NULL);
309 mutex_unlock(&port->mutex); 296 mutex_unlock(&port->mutex);
310bailout_serial_put:
311 usb_serial_put(serial);
312 return retval; 297 return retval;
313} 298}
314 299
@@ -355,9 +340,6 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
355{ 340{
356 struct usb_serial_port *port = tty->driver_data; 341 struct usb_serial_port *port = tty->driver_data;
357 342
358 if (!port)
359 return;
360
361 dbg("%s - port %d", __func__, port->number); 343 dbg("%s - port %d", __func__, port->number);
362 344
363 if (tty_port_close_start(&port->port, tty, filp) == 0) 345 if (tty_port_close_start(&port->port, tty, filp) == 0)
@@ -365,7 +347,6 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
365 serial_do_down(port); 347 serial_do_down(port);
366 tty_port_close_end(&port->port, tty); 348 tty_port_close_end(&port->port, tty);
367 tty_port_tty_set(&port->port, NULL); 349 tty_port_tty_set(&port->port, NULL);
368
369} 350}
370 351
371/** 352/**
@@ -386,9 +367,11 @@ static void serial_do_free(struct tty_struct *tty)
386 /* The console is magical. Do not hang up the console hardware 367 /* The console is magical. Do not hang up the console hardware
387 * or there will be tears. 368 * or there will be tears.
388 */ 369 */
389 if (port == NULL || port->console) 370 if (port->console)
390 return; 371 return;
391 372
373 tty->driver_data = NULL;
374
392 serial = port->serial; 375 serial = port->serial;
393 owner = serial->type->driver.owner; 376 owner = serial->type->driver.owner;
394 377