aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/usb-serial.c
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-07-22 06:09:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-22 16:03:22 -0400
commit95da310e66ee8090119596c70ca8432e57f9a97f (patch)
tree7f18c30e9c9ad4d7d53df6453fa338be06f09a85 /drivers/usb/serial/usb-serial.c
parent1aa3692da57c773e5c76de55c5c4a953962d360e (diff)
usb_serial: API all change
USB serial likes to use port->tty back pointers for the real work it does and to do so without any actual locking. Unfortunately when you consider hangup events, hangup/parallel reopen or even worse hangup followed by parallel close events the tty->port and port->tty pointers are not guaranteed to be the same as port->tty is the active tty while tty->port is the port the tty may or may not still be attached to. So rework the entire API to pass the tty struct. For console cases we need to pass both for now. This shows up multiple drivers that immediately crash with USB console some of which have been fixed in the process. Longer term we need a proper tty as console abstraction Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb/serial/usb-serial.c')
-rw-r--r--drivers/usb/serial/usb-serial.c82
1 files changed, 41 insertions, 41 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 353798631903..ffaed8ace066 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -143,7 +143,7 @@ static void destroy_serial(struct kref *kref)
143 return_serial(serial); 143 return_serial(serial);
144 144
145 for (i = 0; i < serial->num_ports; ++i) 145 for (i = 0; i < serial->num_ports; ++i)
146 serial->port[i]->open_count = 0; 146 serial->port[i]->port.count = 0;
147 147
148 /* the ports are cleaned up and released in port_release() */ 148 /* the ports are cleaned up and released in port_release() */
149 for (i = 0; i < serial->num_ports; ++i) 149 for (i = 0; i < serial->num_ports; ++i)
@@ -208,14 +208,14 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
208 goto bailout_kref_put; 208 goto bailout_kref_put;
209 } 209 }
210 210
211 ++port->open_count; 211 ++port->port.count;
212 212
213 /* set up our port structure making the tty driver 213 /* set up our port structure making the tty driver
214 * remember our port object, and us it */ 214 * remember our port object, and us it */
215 tty->driver_data = port; 215 tty->driver_data = port;
216 port->tty = tty; 216 port->port.tty = tty;
217 217
218 if (port->open_count == 1) { 218 if (port->port.count == 1) {
219 219
220 /* lock this module before we call it 220 /* lock this module before we call it
221 * this may fail, which means we must bail out, 221 * this may fail, which means we must bail out,
@@ -230,7 +230,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
230 goto bailout_module_put; 230 goto bailout_module_put;
231 /* only call the device specific open if this 231 /* only call the device specific open if this
232 * is the first time the port is opened */ 232 * is the first time the port is opened */
233 retval = serial->type->open(port, filp); 233 retval = serial->type->open(tty, port, filp);
234 if (retval) 234 if (retval)
235 goto bailout_interface_put; 235 goto bailout_interface_put;
236 } 236 }
@@ -243,9 +243,9 @@ bailout_interface_put:
243bailout_module_put: 243bailout_module_put:
244 module_put(serial->type->driver.owner); 244 module_put(serial->type->driver.owner);
245bailout_mutex_unlock: 245bailout_mutex_unlock:
246 port->open_count = 0; 246 port->port.count = 0;
247 tty->driver_data = NULL; 247 tty->driver_data = NULL;
248 port->tty = NULL; 248 port->port.tty = NULL;
249 mutex_unlock(&port->mutex); 249 mutex_unlock(&port->mutex);
250bailout_kref_put: 250bailout_kref_put:
251 usb_serial_put(serial); 251 usb_serial_put(serial);
@@ -263,26 +263,26 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
263 263
264 mutex_lock(&port->mutex); 264 mutex_lock(&port->mutex);
265 265
266 if (port->open_count == 0) { 266 if (port->port.count == 0) {
267 mutex_unlock(&port->mutex); 267 mutex_unlock(&port->mutex);
268 return; 268 return;
269 } 269 }
270 270
271 --port->open_count; 271 --port->port.count;
272 if (port->open_count == 0) 272 if (port->port.count == 0)
273 /* only call the device specific close if this 273 /* only call the device specific close if this
274 * port is being closed by the last owner */ 274 * port is being closed by the last owner */
275 port->serial->type->close(port, filp); 275 port->serial->type->close(tty, port, filp);
276 276
277 if (port->open_count == (port->console? 1 : 0)) { 277 if (port->port.count == (port->console? 1 : 0)) {
278 if (port->tty) { 278 if (port->port.tty) {
279 if (port->tty->driver_data) 279 if (port->port.tty->driver_data)
280 port->tty->driver_data = NULL; 280 port->port.tty->driver_data = NULL;
281 port->tty = NULL; 281 port->port.tty = NULL;
282 } 282 }
283 } 283 }
284 284
285 if (port->open_count == 0) { 285 if (port->port.count == 0) {
286 mutex_lock(&port->serial->disc_mutex); 286 mutex_lock(&port->serial->disc_mutex);
287 if (!port->serial->disconnected) 287 if (!port->serial->disconnected)
288 usb_autopm_put_interface(port->serial->interface); 288 usb_autopm_put_interface(port->serial->interface);
@@ -304,12 +304,12 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int
304 304
305 dbg("%s - port %d, %d byte(s)", __func__, port->number, count); 305 dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
306 306
307 /* open_count is managed under the mutex lock for the tty so cannot 307 /* count is managed under the mutex lock for the tty so cannot
308 drop to zero until after the last close completes */ 308 drop to zero until after the last close completes */
309 WARN_ON(!port->open_count); 309 WARN_ON(!port->port.count);
310 310
311 /* pass on to the driver specific version of this function */ 311 /* pass on to the driver specific version of this function */
312 retval = port->serial->type->write(port, buf, count); 312 retval = port->serial->type->write(tty, port, buf, count);
313 313
314exit: 314exit:
315 return retval; 315 return retval;
@@ -319,9 +319,9 @@ static int serial_write_room (struct tty_struct *tty)
319{ 319{
320 struct usb_serial_port *port = tty->driver_data; 320 struct usb_serial_port *port = tty->driver_data;
321 dbg("%s - port %d", __func__, port->number); 321 dbg("%s - port %d", __func__, port->number);
322 WARN_ON(!port->open_count); 322 WARN_ON(!port->port.count);
323 /* pass on to the driver specific version of this function */ 323 /* pass on to the driver specific version of this function */
324 return port->serial->type->write_room(port); 324 return port->serial->type->write_room(tty);
325} 325}
326 326
327static int serial_chars_in_buffer (struct tty_struct *tty) 327static int serial_chars_in_buffer (struct tty_struct *tty)
@@ -329,9 +329,9 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
329 struct usb_serial_port *port = tty->driver_data; 329 struct usb_serial_port *port = tty->driver_data;
330 dbg("%s = port %d", __func__, port->number); 330 dbg("%s = port %d", __func__, port->number);
331 331
332 WARN_ON(!port->open_count); 332 WARN_ON(!port->port.count);
333 /* pass on to the driver specific version of this function */ 333 /* pass on to the driver specific version of this function */
334 return port->serial->type->chars_in_buffer(port); 334 return port->serial->type->chars_in_buffer(tty);
335} 335}
336 336
337static void serial_throttle (struct tty_struct * tty) 337static void serial_throttle (struct tty_struct * tty)
@@ -339,10 +339,10 @@ static void serial_throttle (struct tty_struct * tty)
339 struct usb_serial_port *port = tty->driver_data; 339 struct usb_serial_port *port = tty->driver_data;
340 dbg("%s - port %d", __func__, port->number); 340 dbg("%s - port %d", __func__, port->number);
341 341
342 WARN_ON(!port->open_count); 342 WARN_ON(!port->port.count);
343 /* pass on to the driver specific version of this function */ 343 /* pass on to the driver specific version of this function */
344 if (port->serial->type->throttle) 344 if (port->serial->type->throttle)
345 port->serial->type->throttle(port); 345 port->serial->type->throttle(tty);
346} 346}
347 347
348static void serial_unthrottle (struct tty_struct * tty) 348static void serial_unthrottle (struct tty_struct * tty)
@@ -350,10 +350,10 @@ static void serial_unthrottle (struct tty_struct * tty)
350 struct usb_serial_port *port = tty->driver_data; 350 struct usb_serial_port *port = tty->driver_data;
351 dbg("%s - port %d", __func__, port->number); 351 dbg("%s - port %d", __func__, port->number);
352 352
353 WARN_ON(!port->open_count); 353 WARN_ON(!port->port.count);
354 /* pass on to the driver specific version of this function */ 354 /* pass on to the driver specific version of this function */
355 if (port->serial->type->unthrottle) 355 if (port->serial->type->unthrottle)
356 port->serial->type->unthrottle(port); 356 port->serial->type->unthrottle(tty);
357} 357}
358 358
359static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) 359static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
@@ -363,12 +363,12 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
363 363
364 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); 364 dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd);
365 365
366 WARN_ON(!port->open_count); 366 WARN_ON(!port->port.count);
367 367
368 /* pass on to the driver specific version of this function if it is available */ 368 /* pass on to the driver specific version of this function if it is available */
369 if (port->serial->type->ioctl) { 369 if (port->serial->type->ioctl) {
370 lock_kernel(); 370 lock_kernel();
371 retval = port->serial->type->ioctl(port, file, cmd, arg); 371 retval = port->serial->type->ioctl(tty, file, cmd, arg);
372 unlock_kernel(); 372 unlock_kernel();
373 } 373 }
374 else 374 else
@@ -381,10 +381,10 @@ static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
381 struct usb_serial_port *port = tty->driver_data; 381 struct usb_serial_port *port = tty->driver_data;
382 dbg("%s - port %d", __func__, port->number); 382 dbg("%s - port %d", __func__, port->number);
383 383
384 WARN_ON(!port->open_count); 384 WARN_ON(!port->port.count);
385 /* pass on to the driver specific version of this function if it is available */ 385 /* pass on to the driver specific version of this function if it is available */
386 if (port->serial->type->set_termios) 386 if (port->serial->type->set_termios)
387 port->serial->type->set_termios(port, old); 387 port->serial->type->set_termios(tty, port, old);
388 else 388 else
389 tty_termios_copy_hw(tty->termios, old); 389 tty_termios_copy_hw(tty->termios, old);
390} 390}
@@ -395,11 +395,11 @@ static void serial_break (struct tty_struct *tty, int break_state)
395 395
396 dbg("%s - port %d", __func__, port->number); 396 dbg("%s - port %d", __func__, port->number);
397 397
398 WARN_ON(!port->open_count); 398 WARN_ON(!port->port.count);
399 /* pass on to the driver specific version of this function if it is available */ 399 /* pass on to the driver specific version of this function if it is available */
400 if (port->serial->type->break_ctl) { 400 if (port->serial->type->break_ctl) {
401 lock_kernel(); 401 lock_kernel();
402 port->serial->type->break_ctl(port, break_state); 402 port->serial->type->break_ctl(tty, break_state);
403 unlock_kernel(); 403 unlock_kernel();
404 } 404 }
405} 405}
@@ -457,9 +457,9 @@ static int serial_tiocmget (struct tty_struct *tty, struct file *file)
457 457
458 dbg("%s - port %d", __func__, port->number); 458 dbg("%s - port %d", __func__, port->number);
459 459
460 WARN_ON(!port->open_count); 460 WARN_ON(!port->port.count);
461 if (port->serial->type->tiocmget) 461 if (port->serial->type->tiocmget)
462 return port->serial->type->tiocmget(port, file); 462 return port->serial->type->tiocmget(tty, file);
463 return -EINVAL; 463 return -EINVAL;
464} 464}
465 465
@@ -470,9 +470,9 @@ static int serial_tiocmset (struct tty_struct *tty, struct file *file,
470 470
471 dbg("%s - port %d", __func__, port->number); 471 dbg("%s - port %d", __func__, port->number);
472 472
473 WARN_ON(!port->open_count); 473 WARN_ON(!port->port.count);
474 if (port->serial->type->tiocmset) 474 if (port->serial->type->tiocmset)
475 return port->serial->type->tiocmset(port, file, set, clear); 475 return port->serial->type->tiocmset(tty, file, set, clear);
476 return -EINVAL; 476 return -EINVAL;
477} 477}
478 478
@@ -497,7 +497,7 @@ static void usb_serial_port_work(struct work_struct *work)
497 if (!port) 497 if (!port)
498 return; 498 return;
499 499
500 tty = port->tty; 500 tty = port->port.tty;
501 if (!tty) 501 if (!tty)
502 return; 502 return;
503 503
@@ -1010,8 +1010,8 @@ void usb_serial_disconnect(struct usb_interface *interface)
1010 for (i = 0; i < serial->num_ports; ++i) { 1010 for (i = 0; i < serial->num_ports; ++i) {
1011 port = serial->port[i]; 1011 port = serial->port[i];
1012 if (port) { 1012 if (port) {
1013 if (port->tty) 1013 if (port->port.tty)
1014 tty_hangup(port->tty); 1014 tty_hangup(port->port.tty);
1015 kill_traffic(port); 1015 kill_traffic(port);
1016 } 1016 }
1017 } 1017 }