aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/oti6858.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/oti6858.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/oti6858.c')
-rw-r--r--drivers/usb/serial/oti6858.c119
1 files changed, 48 insertions, 71 deletions
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index a9625c180dc3..069d276a5276 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -140,22 +140,23 @@ struct oti6858_control_pkt {
140 && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) ) 140 && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) )
141 141
142/* function prototypes */ 142/* function prototypes */
143static int oti6858_open(struct usb_serial_port *port, struct file *filp); 143static int oti6858_open(struct tty_struct *tty,
144static void oti6858_close(struct usb_serial_port *port, struct file *filp); 144 struct usb_serial_port *port, struct file *filp);
145static void oti6858_set_termios(struct usb_serial_port *port, 145static void oti6858_close(struct tty_struct *tty,
146 struct ktermios *old); 146 struct usb_serial_port *port, struct file *filp);
147static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, 147static void oti6858_set_termios(struct tty_struct *tty,
148 struct usb_serial_port *port, struct ktermios *old);
149static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
148 unsigned int cmd, unsigned long arg); 150 unsigned int cmd, unsigned long arg);
149static void oti6858_read_int_callback(struct urb *urb); 151static void oti6858_read_int_callback(struct urb *urb);
150static void oti6858_read_bulk_callback(struct urb *urb); 152static void oti6858_read_bulk_callback(struct urb *urb);
151static void oti6858_write_bulk_callback(struct urb *urb); 153static void oti6858_write_bulk_callback(struct urb *urb);
152static int oti6858_write(struct usb_serial_port *port, 154static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
153 const unsigned char *buf, int count); 155 const unsigned char *buf, int count);
154static int oti6858_write_room(struct usb_serial_port *port); 156static int oti6858_write_room(struct tty_struct *tty);
155static void oti6858_break_ctl(struct usb_serial_port *port, int break_state); 157static int oti6858_chars_in_buffer(struct tty_struct *tty);
156static int oti6858_chars_in_buffer(struct usb_serial_port *port); 158static int oti6858_tiocmget(struct tty_struct *tty, struct file *file);
157static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file); 159static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
158static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
159 unsigned int set, unsigned int clear); 160 unsigned int set, unsigned int clear);
160static int oti6858_startup(struct usb_serial *serial); 161static int oti6858_startup(struct usb_serial *serial);
161static void oti6858_shutdown(struct usb_serial *serial); 162static void oti6858_shutdown(struct usb_serial *serial);
@@ -184,7 +185,6 @@ static struct usb_serial_driver oti6858_device = {
184 .close = oti6858_close, 185 .close = oti6858_close,
185 .write = oti6858_write, 186 .write = oti6858_write,
186 .ioctl = oti6858_ioctl, 187 .ioctl = oti6858_ioctl,
187 .break_ctl = oti6858_break_ctl,
188 .set_termios = oti6858_set_termios, 188 .set_termios = oti6858_set_termios,
189 .tiocmget = oti6858_tiocmget, 189 .tiocmget = oti6858_tiocmget,
190 .tiocmset = oti6858_tiocmset, 190 .tiocmset = oti6858_tiocmset,
@@ -395,7 +395,7 @@ static int oti6858_startup(struct usb_serial *serial)
395 return -ENOMEM; 395 return -ENOMEM;
396} 396}
397 397
398static int oti6858_write(struct usb_serial_port *port, 398static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
399 const unsigned char *buf, int count) 399 const unsigned char *buf, int count)
400{ 400{
401 struct oti6858_private *priv = usb_get_serial_port_data(port); 401 struct oti6858_private *priv = usb_get_serial_port_data(port);
@@ -413,8 +413,9 @@ static int oti6858_write(struct usb_serial_port *port,
413 return count; 413 return count;
414} 414}
415 415
416static int oti6858_write_room(struct usb_serial_port *port) 416static int oti6858_write_room(struct tty_struct *tty)
417{ 417{
418 struct usb_serial_port *port = tty->driver_data;
418 struct oti6858_private *priv = usb_get_serial_port_data(port); 419 struct oti6858_private *priv = usb_get_serial_port_data(port);
419 int room = 0; 420 int room = 0;
420 unsigned long flags; 421 unsigned long flags;
@@ -428,8 +429,9 @@ static int oti6858_write_room(struct usb_serial_port *port)
428 return room; 429 return room;
429} 430}
430 431
431static int oti6858_chars_in_buffer(struct usb_serial_port *port) 432static int oti6858_chars_in_buffer(struct tty_struct *tty)
432{ 433{
434 struct usb_serial_port *port = tty->driver_data;
433 struct oti6858_private *priv = usb_get_serial_port_data(port); 435 struct oti6858_private *priv = usb_get_serial_port_data(port);
434 int chars = 0; 436 int chars = 0;
435 unsigned long flags; 437 unsigned long flags;
@@ -443,8 +445,8 @@ static int oti6858_chars_in_buffer(struct usb_serial_port *port)
443 return chars; 445 return chars;
444} 446}
445 447
446static void oti6858_set_termios(struct usb_serial_port *port, 448static void oti6858_set_termios(struct tty_struct *tty,
447 struct ktermios *old_termios) 449 struct usb_serial_port *port, struct ktermios *old_termios)
448{ 450{
449 struct oti6858_private *priv = usb_get_serial_port_data(port); 451 struct oti6858_private *priv = usb_get_serial_port_data(port);
450 unsigned long flags; 452 unsigned long flags;
@@ -455,22 +457,22 @@ static void oti6858_set_termios(struct usb_serial_port *port,
455 457
456 dbg("%s(port = %d)", __func__, port->number); 458 dbg("%s(port = %d)", __func__, port->number);
457 459
458 if (!port->tty || !port->tty->termios) { 460 if (!tty) {
459 dbg("%s(): no tty structures", __func__); 461 dbg("%s(): no tty structures", __func__);
460 return; 462 return;
461 } 463 }
462 464
463 spin_lock_irqsave(&priv->lock, flags); 465 spin_lock_irqsave(&priv->lock, flags);
464 if (!priv->flags.termios_initialized) { 466 if (!priv->flags.termios_initialized) {
465 *(port->tty->termios) = tty_std_termios; 467 *(tty->termios) = tty_std_termios;
466 port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL; 468 tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
469 tty->termios->c_ispeed = 38400;
470 tty->termios->c_ospeed = 38400;
467 priv->flags.termios_initialized = 1; 471 priv->flags.termios_initialized = 1;
468 port->tty->termios->c_ispeed = 38400;
469 port->tty->termios->c_ospeed = 38400;
470 } 472 }
471 spin_unlock_irqrestore(&priv->lock, flags); 473 spin_unlock_irqrestore(&priv->lock, flags);
472 474
473 cflag = port->tty->termios->c_cflag; 475 cflag = tty->termios->c_cflag;
474 476
475 spin_lock_irqsave(&priv->lock, flags); 477 spin_lock_irqsave(&priv->lock, flags);
476 divisor = priv->pending_setup.divisor; 478 divisor = priv->pending_setup.divisor;
@@ -500,7 +502,7 @@ static void oti6858_set_termios(struct usb_serial_port *port,
500 * guarantee that any other baud rate will work (especially 502 * guarantee that any other baud rate will work (especially
501 * the higher ones) 503 * the higher ones)
502 */ 504 */
503 br = tty_get_baud_rate(port->tty); 505 br = tty_get_baud_rate(tty);
504 if (br == 0) { 506 if (br == 0) {
505 divisor = 0; 507 divisor = 0;
506 } else { 508 } else {
@@ -511,7 +513,7 @@ static void oti6858_set_termios(struct usb_serial_port *port,
511 new_divisor = (96000000 + 8 * br) / (16 * br); 513 new_divisor = (96000000 + 8 * br) / (16 * br);
512 real_br = 96000000 / (16 * new_divisor); 514 real_br = 96000000 / (16 * new_divisor);
513 divisor = cpu_to_le16(new_divisor); 515 divisor = cpu_to_le16(new_divisor);
514 tty_encode_baud_rate(port->tty, real_br, real_br); 516 tty_encode_baud_rate(tty, real_br, real_br);
515 } 517 }
516 518
517 frame_fmt &= ~FMT_STOP_BITS_MASK; 519 frame_fmt &= ~FMT_STOP_BITS_MASK;
@@ -564,7 +566,8 @@ static void oti6858_set_termios(struct usb_serial_port *port,
564 spin_unlock_irqrestore(&priv->lock, flags); 566 spin_unlock_irqrestore(&priv->lock, flags);
565} 567}
566 568
567static int oti6858_open(struct usb_serial_port *port, struct file *filp) 569static int oti6858_open(struct tty_struct *tty,
570 struct usb_serial_port *port, struct file *filp)
568{ 571{
569 struct oti6858_private *priv = usb_get_serial_port_data(port); 572 struct oti6858_private *priv = usb_get_serial_port_data(port);
570 struct ktermios tmp_termios; 573 struct ktermios tmp_termios;
@@ -578,7 +581,7 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
578 usb_clear_halt(serial->dev, port->write_urb->pipe); 581 usb_clear_halt(serial->dev, port->write_urb->pipe);
579 usb_clear_halt(serial->dev, port->read_urb->pipe); 582 usb_clear_halt(serial->dev, port->read_urb->pipe);
580 583
581 if (port->open_count != 1) 584 if (port->port.count != 1)
582 return 0; 585 return 0;
583 586
584 if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) { 587 if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
@@ -617,18 +620,19 @@ static int oti6858_open(struct usb_serial_port *port, struct file *filp)
617 if (result != 0) { 620 if (result != 0) {
618 dev_err(&port->dev, "%s(): usb_submit_urb() failed" 621 dev_err(&port->dev, "%s(): usb_submit_urb() failed"
619 " with error %d\n", __func__, result); 622 " with error %d\n", __func__, result);
620 oti6858_close(port, NULL); 623 oti6858_close(tty, port, NULL);
621 return -EPROTO; 624 return -EPROTO;
622 } 625 }
623 626
624 /* setup termios */ 627 /* setup termios */
625 if (port->tty) 628 if (tty)
626 oti6858_set_termios(port, &tmp_termios); 629 oti6858_set_termios(tty, port, &tmp_termios);
627 630
628 return 0; 631 return 0;
629} 632}
630 633
631static void oti6858_close(struct usb_serial_port *port, struct file *filp) 634static void oti6858_close(struct tty_struct *tty,
635 struct usb_serial_port *port, struct file *filp)
632{ 636{
633 struct oti6858_private *priv = usb_get_serial_port_data(port); 637 struct oti6858_private *priv = usb_get_serial_port_data(port);
634 unsigned long flags; 638 unsigned long flags;
@@ -641,7 +645,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
641 spin_lock_irqsave(&priv->lock, flags); 645 spin_lock_irqsave(&priv->lock, flags);
642 timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */ 646 timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */
643 init_waitqueue_entry(&wait, current); 647 init_waitqueue_entry(&wait, current);
644 add_wait_queue(&port->tty->write_wait, &wait); 648 add_wait_queue(&tty->write_wait, &wait);
645 dbg("%s(): entering wait loop", __func__); 649 dbg("%s(): entering wait loop", __func__);
646 for (;;) { 650 for (;;) {
647 set_current_state(TASK_INTERRUPTIBLE); 651 set_current_state(TASK_INTERRUPTIBLE);
@@ -654,7 +658,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
654 spin_lock_irqsave(&priv->lock, flags); 658 spin_lock_irqsave(&priv->lock, flags);
655 } 659 }
656 set_current_state(TASK_RUNNING); 660 set_current_state(TASK_RUNNING);
657 remove_wait_queue(&port->tty->write_wait, &wait); 661 remove_wait_queue(&tty->write_wait, &wait);
658 dbg("%s(): after wait loop", __func__); 662 dbg("%s(): after wait loop", __func__);
659 663
660 /* clear out any remaining data in the buffer */ 664 /* clear out any remaining data in the buffer */
@@ -669,7 +673,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
669 /* data is in the buffer to compute a delay */ 673 /* data is in the buffer to compute a delay */
670 /* that is not unnecessarily long) */ 674 /* that is not unnecessarily long) */
671 /* FIXME 675 /* FIXME
672 bps = tty_get_baud_rate(port->tty); 676 bps = tty_get_baud_rate(tty);
673 if (bps > 1200) 677 if (bps > 1200)
674 timeout = max((HZ*2560)/bps,HZ/10); 678 timeout = max((HZ*2560)/bps,HZ/10);
675 else 679 else
@@ -690,7 +694,7 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
690 usb_kill_urb(port->interrupt_in_urb); 694 usb_kill_urb(port->interrupt_in_urb);
691 695
692 /* 696 /*
693 if (port->tty && (port->tty->termios->c_cflag) & HUPCL) { 697 if (tty && (tty->termios->c_cflag) & HUPCL) {
694 // drop DTR and RTS 698 // drop DTR and RTS
695 spin_lock_irqsave(&priv->lock, flags); 699 spin_lock_irqsave(&priv->lock, flags);
696 priv->pending_setup.control &= ~CONTROL_MASK; 700 priv->pending_setup.control &= ~CONTROL_MASK;
@@ -699,9 +703,10 @@ static void oti6858_close(struct usb_serial_port *port, struct file *filp)
699 */ 703 */
700} 704}
701 705
702static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file, 706static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
703 unsigned int set, unsigned int clear) 707 unsigned int set, unsigned int clear)
704{ 708{
709 struct usb_serial_port *port = tty->driver_data;
705 struct oti6858_private *priv = usb_get_serial_port_data(port); 710 struct oti6858_private *priv = usb_get_serial_port_data(port);
706 unsigned long flags; 711 unsigned long flags;
707 u8 control; 712 u8 control;
@@ -732,8 +737,9 @@ static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
732 return 0; 737 return 0;
733} 738}
734 739
735static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file) 740static int oti6858_tiocmget(struct tty_struct *tty, struct file *file)
736{ 741{
742 struct usb_serial_port *port = tty->driver_data;
737 struct oti6858_private *priv = usb_get_serial_port_data(port); 743 struct oti6858_private *priv = usb_get_serial_port_data(port);
738 unsigned long flags; 744 unsigned long flags;
739 unsigned pin_state; 745 unsigned pin_state;
@@ -802,26 +808,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
802 return 0; 808 return 0;
803} 809}
804 810
805static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, 811static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
806 unsigned int cmd, unsigned long arg) 812 unsigned int cmd, unsigned long arg)
807{ 813{
808 void __user *user_arg = (void __user *) arg; 814 struct usb_serial_port *port = tty->driver_data;
809 unsigned int x;
810 815
811 dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)", 816 dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
812 __func__, port->number, cmd, arg); 817 __func__, port->number, cmd, arg);
813 818
814 switch (cmd) { 819 switch (cmd) {
815 case TIOCMBIS:
816 if (copy_from_user(&x, user_arg, sizeof(x)))
817 return -EFAULT;
818 return oti6858_tiocmset(port, NULL, x, 0);
819
820 case TIOCMBIC:
821 if (copy_from_user(&x, user_arg, sizeof(x)))
822 return -EFAULT;
823 return oti6858_tiocmset(port, NULL, 0, x);
824
825 case TIOCMIWAIT: 820 case TIOCMIWAIT:
826 dbg("%s(): TIOCMIWAIT", __func__); 821 dbg("%s(): TIOCMIWAIT", __func__);
827 return wait_modem_info(port, arg); 822 return wait_modem_info(port, arg);
@@ -834,24 +829,6 @@ static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
834 return -ENOIOCTLCMD; 829 return -ENOIOCTLCMD;
835} 830}
836 831
837static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
838{
839 int state;
840
841 dbg("%s(port = %d)", __func__, port->number);
842
843 state = (break_state == 0) ? 0 : 1;
844 dbg("%s(): turning break %s", __func__, state ? "on" : "off");
845
846 /* FIXME */
847/*
848 result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
849 BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
850 0, NULL, 0, 100);
851 if (result != 0)
852 dbg("%s(): error sending break", __func__);
853 */
854}
855 832
856static void oti6858_shutdown(struct usb_serial *serial) 833static void oti6858_shutdown(struct usb_serial *serial)
857{ 834{
@@ -1002,7 +979,7 @@ static void oti6858_read_bulk_callback(struct urb *urb)
1002 spin_unlock_irqrestore(&priv->lock, flags); 979 spin_unlock_irqrestore(&priv->lock, flags);
1003 980
1004 if (status != 0) { 981 if (status != 0) {
1005 if (!port->open_count) { 982 if (!port->port.count) {
1006 dbg("%s(): port is closed, exiting", __func__); 983 dbg("%s(): port is closed, exiting", __func__);
1007 return; 984 return;
1008 } 985 }
@@ -1020,14 +997,14 @@ static void oti6858_read_bulk_callback(struct urb *urb)
1020 return; 997 return;
1021 } 998 }
1022 999
1023 tty = port->tty; 1000 tty = port->port.tty;
1024 if (tty != NULL && urb->actual_length > 0) { 1001 if (tty != NULL && urb->actual_length > 0) {
1025 tty_insert_flip_string(tty, data, urb->actual_length); 1002 tty_insert_flip_string(tty, data, urb->actual_length);
1026 tty_flip_buffer_push(tty); 1003 tty_flip_buffer_push(tty);
1027 } 1004 }
1028 1005
1029 // schedule the interrupt urb if we are still open */ 1006 // schedule the interrupt urb if we are still open */
1030 if (port->open_count != 0) { 1007 if (port->port.count != 0) {
1031 port->interrupt_in_urb->dev = port->serial->dev; 1008 port->interrupt_in_urb->dev = port->serial->dev;
1032 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); 1009 result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
1033 if (result != 0) { 1010 if (result != 0) {