aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/spcp8x5.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/spcp8x5.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/spcp8x5.c')
-rw-r--r--drivers/usb/serial/spcp8x5.c69
1 files changed, 37 insertions, 32 deletions
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 55b2570b8b8b..58495f5cca1f 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -448,7 +448,8 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
448 448
449/* close the serial port. We should wait for data sending to device 1st and 449/* close the serial port. We should wait for data sending to device 1st and
450 * then kill all urb. */ 450 * then kill all urb. */
451static void spcp8x5_close(struct usb_serial_port *port, struct file *filp) 451static void spcp8x5_close(struct tty_struct *tty,
452 struct usb_serial_port *port, struct file *filp)
452{ 453{
453 struct spcp8x5_private *priv = usb_get_serial_port_data(port); 454 struct spcp8x5_private *priv = usb_get_serial_port_data(port);
454 unsigned long flags; 455 unsigned long flags;
@@ -464,7 +465,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
464 spin_lock_irqsave(&priv->lock, flags); 465 spin_lock_irqsave(&priv->lock, flags);
465 timeout = SPCP8x5_CLOSING_WAIT; 466 timeout = SPCP8x5_CLOSING_WAIT;
466 init_waitqueue_entry(&wait, current); 467 init_waitqueue_entry(&wait, current);
467 add_wait_queue(&port->tty->write_wait, &wait); 468 add_wait_queue(&tty->write_wait, &wait);
468 for (;;) { 469 for (;;) {
469 set_current_state(TASK_INTERRUPTIBLE); 470 set_current_state(TASK_INTERRUPTIBLE);
470 if (ringbuf_avail_data(priv->buf) == 0 || 471 if (ringbuf_avail_data(priv->buf) == 0 ||
@@ -475,7 +476,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
475 spin_lock_irqsave(&priv->lock, flags); 476 spin_lock_irqsave(&priv->lock, flags);
476 } 477 }
477 set_current_state(TASK_RUNNING); 478 set_current_state(TASK_RUNNING);
478 remove_wait_queue(&port->tty->write_wait, &wait); 479 remove_wait_queue(&tty->write_wait, &wait);
479 480
480 /* clear out any remaining data in the buffer */ 481 /* clear out any remaining data in the buffer */
481 clear_ringbuf(priv->buf); 482 clear_ringbuf(priv->buf);
@@ -486,7 +487,7 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
486 * flow control for data rates of 1200 bps or more, for lower rates we 487 * flow control for data rates of 1200 bps or more, for lower rates we
487 * should really know how much data is in the buffer to compute a delay 488 * should really know how much data is in the buffer to compute a delay
488 * that is not unnecessarily long) */ 489 * that is not unnecessarily long) */
489 bps = tty_get_baud_rate(port->tty); 490 bps = tty_get_baud_rate(tty);
490 if (bps > 1200) 491 if (bps > 1200)
491 timeout = max((HZ*2560) / bps, HZ/10); 492 timeout = max((HZ*2560) / bps, HZ/10);
492 else 493 else
@@ -495,8 +496,8 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
495 schedule_timeout(timeout); 496 schedule_timeout(timeout);
496 497
497 /* clear control lines */ 498 /* clear control lines */
498 if (port->tty) { 499 if (tty) {
499 c_cflag = port->tty->termios->c_cflag; 500 c_cflag = tty->termios->c_cflag;
500 if (c_cflag & HUPCL) { 501 if (c_cflag & HUPCL) {
501 spin_lock_irqsave(&priv->lock, flags); 502 spin_lock_irqsave(&priv->lock, flags);
502 priv->line_control = 0; 503 priv->line_control = 0;
@@ -518,14 +519,14 @@ static void spcp8x5_close(struct usb_serial_port *port, struct file *filp)
518} 519}
519 520
520/* set the serial param for transfer. we should check if we really need to 521/* set the serial param for transfer. we should check if we really need to
521 * transfer. then if be set flow contorl we should do this too. */ 522 * transfer. if we set flow control we should do this too. */
522static void spcp8x5_set_termios(struct usb_serial_port *port, 523static void spcp8x5_set_termios(struct tty_struct *tty,
523 struct ktermios *old_termios) 524 struct usb_serial_port *port, struct ktermios *old_termios)
524{ 525{
525 struct usb_serial *serial = port->serial; 526 struct usb_serial *serial = port->serial;
526 struct spcp8x5_private *priv = usb_get_serial_port_data(port); 527 struct spcp8x5_private *priv = usb_get_serial_port_data(port);
527 unsigned long flags; 528 unsigned long flags;
528 unsigned int cflag = port->tty->termios->c_cflag; 529 unsigned int cflag = tty->termios->c_cflag;
529 unsigned int old_cflag = old_termios->c_cflag; 530 unsigned int old_cflag = old_termios->c_cflag;
530 unsigned short uartdata; 531 unsigned short uartdata;
531 unsigned char buf[2] = {0, 0}; 532 unsigned char buf[2] = {0, 0};
@@ -533,21 +534,19 @@ static void spcp8x5_set_termios(struct usb_serial_port *port,
533 int i; 534 int i;
534 u8 control; 535 u8 control;
535 536
536 if ((!port->tty) || (!port->tty->termios))
537 return;
538
539 /* for the 1st time call this function */ 537 /* for the 1st time call this function */
540 spin_lock_irqsave(&priv->lock, flags); 538 spin_lock_irqsave(&priv->lock, flags);
541 if (!priv->termios_initialized) { 539 if (!priv->termios_initialized) {
542 *(port->tty->termios) = tty_std_termios; 540 *(tty->termios) = tty_std_termios;
543 port->tty->termios->c_cflag = B115200 | CS8 | CREAD | 541 tty->termios->c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
544 HUPCL | CLOCAL; 542 tty->termios->c_ispeed = 115200;
543 tty->termios->c_ospeed = 115200;
545 priv->termios_initialized = 1; 544 priv->termios_initialized = 1;
546 } 545 }
547 spin_unlock_irqrestore(&priv->lock, flags); 546 spin_unlock_irqrestore(&priv->lock, flags);
548 547
549 /* check that they really want us to change something */ 548 /* check that they really want us to change something */
550 if (!tty_termios_hw_change(port->tty->termios, old_termios)) 549 if (!tty_termios_hw_change(tty->termios, old_termios))
551 return; 550 return;
552 551
553 /* set DTR/RTS active */ 552 /* set DTR/RTS active */
@@ -567,7 +566,7 @@ static void spcp8x5_set_termios(struct usb_serial_port *port,
567 } 566 }
568 567
569 /* Set Baud Rate */ 568 /* Set Baud Rate */
570 baud = tty_get_baud_rate(port->tty);; 569 baud = tty_get_baud_rate(tty);;
571 switch (baud) { 570 switch (baud) {
572 case 300: buf[0] = 0x00; break; 571 case 300: buf[0] = 0x00; break;
573 case 600: buf[0] = 0x01; break; 572 case 600: buf[0] = 0x01; break;
@@ -643,7 +642,8 @@ static void spcp8x5_set_termios(struct usb_serial_port *port,
643 642
644/* open the serial port. do some usb system call. set termios and get the line 643/* open the serial port. do some usb system call. set termios and get the line
645 * status of the device. then submit the read urb */ 644 * status of the device. then submit the read urb */
646static int spcp8x5_open(struct usb_serial_port *port, struct file *filp) 645static int spcp8x5_open(struct tty_struct *tty,
646 struct usb_serial_port *port, struct file *filp)
647{ 647{
648 struct ktermios tmp_termios; 648 struct ktermios tmp_termios;
649 struct usb_serial *serial = port->serial; 649 struct usb_serial *serial = port->serial;
@@ -665,7 +665,7 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
665 return ret; 665 return ret;
666 666
667 spin_lock_irqsave(&priv->lock, flags); 667 spin_lock_irqsave(&priv->lock, flags);
668 if (port->tty->termios->c_cflag & CBAUD) 668 if (tty && (tty->termios->c_cflag & CBAUD))
669 priv->line_control = MCR_DTR | MCR_RTS; 669 priv->line_control = MCR_DTR | MCR_RTS;
670 else 670 else
671 priv->line_control = 0; 671 priv->line_control = 0;
@@ -674,8 +674,8 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
674 spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); 674 spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
675 675
676 /* Setup termios */ 676 /* Setup termios */
677 if (port->tty) 677 if (tty)
678 spcp8x5_set_termios(port, &tmp_termios); 678 spcp8x5_set_termios(tty, port, &tmp_termios);
679 679
680 spcp8x5_get_msr(serial->dev, &status, priv->type); 680 spcp8x5_get_msr(serial->dev, &status, priv->type);
681 681
@@ -690,7 +690,7 @@ static int spcp8x5_open(struct usb_serial_port *port, struct file *filp)
690 port->read_urb->dev = serial->dev; 690 port->read_urb->dev = serial->dev;
691 ret = usb_submit_urb(port->read_urb, GFP_KERNEL); 691 ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
692 if (ret) { 692 if (ret) {
693 spcp8x5_close(port, NULL); 693 spcp8x5_close(tty, port, NULL);
694 return -EPROTO; 694 return -EPROTO;
695 } 695 }
696 return 0; 696 return 0;
@@ -717,7 +717,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
717 717
718 /* check the urb status */ 718 /* check the urb status */
719 if (urb->status) { 719 if (urb->status) {
720 if (!port->open_count) 720 if (!port->port.count)
721 return; 721 return;
722 if (urb->status == -EPROTO) { 722 if (urb->status == -EPROTO) {
723 /* spcp8x5 mysteriously fails with -EPROTO */ 723 /* spcp8x5 mysteriously fails with -EPROTO */
@@ -755,7 +755,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
755 tty_flag = TTY_FRAME; 755 tty_flag = TTY_FRAME;
756 dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); 756 dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
757 757
758 tty = port->tty; 758 tty = port->port.tty;
759 if (tty && urb->actual_length) { 759 if (tty && urb->actual_length) {
760 tty_buffer_request_room(tty, urb->actual_length + 1); 760 tty_buffer_request_room(tty, urb->actual_length + 1);
761 /* overrun is special, not associated with a char */ 761 /* overrun is special, not associated with a char */
@@ -767,7 +767,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb)
767 } 767 }
768 768
769 /* Schedule the next read _if_ we are still open */ 769 /* Schedule the next read _if_ we are still open */
770 if (port->open_count) { 770 if (port->port.count) {
771 urb->dev = port->serial->dev; 771 urb->dev = port->serial->dev;
772 result = usb_submit_urb(urb , GFP_ATOMIC); 772 result = usb_submit_urb(urb , GFP_ATOMIC);
773 if (result) 773 if (result)
@@ -866,7 +866,7 @@ static void spcp8x5_write_bulk_callback(struct urb *urb)
866} 866}
867 867
868/* write data to ring buffer. and then start the write transfer */ 868/* write data to ring buffer. and then start the write transfer */
869static int spcp8x5_write(struct usb_serial_port *port, 869static int spcp8x5_write(struct tty_struct *tty, struct usb_serial_port *port,
870 const unsigned char *buf, int count) 870 const unsigned char *buf, int count)
871{ 871{
872 struct spcp8x5_private *priv = usb_get_serial_port_data(port); 872 struct spcp8x5_private *priv = usb_get_serial_port_data(port);
@@ -925,9 +925,10 @@ static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
925 return 0; 925 return 0;
926} 926}
927 927
928static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file, 928static int spcp8x5_ioctl(struct tty_struct *tty, struct file *file,
929 unsigned int cmd, unsigned long arg) 929 unsigned int cmd, unsigned long arg)
930{ 930{
931 struct usb_serial_port *port = tty->driver_data;
931 dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); 932 dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
932 933
933 switch (cmd) { 934 switch (cmd) {
@@ -943,9 +944,10 @@ static int spcp8x5_ioctl(struct usb_serial_port *port, struct file *file,
943 return -ENOIOCTLCMD; 944 return -ENOIOCTLCMD;
944} 945}
945 946
946static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file, 947static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file,
947 unsigned int set, unsigned int clear) 948 unsigned int set, unsigned int clear)
948{ 949{
950 struct usb_serial_port *port = tty->driver_data;
949 struct spcp8x5_private *priv = usb_get_serial_port_data(port); 951 struct spcp8x5_private *priv = usb_get_serial_port_data(port);
950 unsigned long flags; 952 unsigned long flags;
951 u8 control; 953 u8 control;
@@ -965,8 +967,9 @@ static int spcp8x5_tiocmset(struct usb_serial_port *port, struct file *file,
965 return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); 967 return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
966} 968}
967 969
968static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file) 970static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file)
969{ 971{
972 struct usb_serial_port *port = tty->driver_data;
970 struct spcp8x5_private *priv = usb_get_serial_port_data(port); 973 struct spcp8x5_private *priv = usb_get_serial_port_data(port);
971 unsigned long flags; 974 unsigned long flags;
972 unsigned int mcr; 975 unsigned int mcr;
@@ -989,8 +992,9 @@ static int spcp8x5_tiocmget(struct usb_serial_port *port, struct file *file)
989} 992}
990 993
991/* get the avail space room in ring buffer */ 994/* get the avail space room in ring buffer */
992static int spcp8x5_write_room(struct usb_serial_port *port) 995static int spcp8x5_write_room(struct tty_struct *tty)
993{ 996{
997 struct usb_serial_port *port = tty->driver_data;
994 struct spcp8x5_private *priv = usb_get_serial_port_data(port); 998 struct spcp8x5_private *priv = usb_get_serial_port_data(port);
995 int room = 0; 999 int room = 0;
996 unsigned long flags; 1000 unsigned long flags;
@@ -1003,8 +1007,9 @@ static int spcp8x5_write_room(struct usb_serial_port *port)
1003} 1007}
1004 1008
1005/* get the number of avail data in write ring buffer */ 1009/* get the number of avail data in write ring buffer */
1006static int spcp8x5_chars_in_buffer(struct usb_serial_port *port) 1010static int spcp8x5_chars_in_buffer(struct tty_struct *tty)
1007{ 1011{
1012 struct usb_serial_port *port = tty->driver_data;
1008 struct spcp8x5_private *priv = usb_get_serial_port_data(port); 1013 struct spcp8x5_private *priv = usb_get_serial_port_data(port);
1009 int chars = 0; 1014 int chars = 0;
1010 unsigned long flags; 1015 unsigned long flags;