diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-12 02:53:38 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-12 02:53:38 -0400 |
commit | bc47ab0241c7c86da4f5e5f82fbca7d45387c18d (patch) | |
tree | b9c33ae8b6de43e44cc5fcbaa3e4a15f18a5ed42 /drivers/usb/serial/spcp8x5.c | |
parent | 37f9ef553bed630957e025504cdcbc76f5de49d5 (diff) | |
parent | 8ebf975608aaebd7feb33d77f07ba21a6380e086 (diff) |
Merge commit 'origin/master' into next
Manual merge of:
arch/powerpc/kernel/asm-offsets.c
Diffstat (limited to 'drivers/usb/serial/spcp8x5.c')
-rw-r--r-- | drivers/usb/serial/spcp8x5.c | 85 |
1 files changed, 31 insertions, 54 deletions
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 5e7528cc81a8..8f7ed8f13996 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c | |||
@@ -446,66 +446,47 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value, | |||
446 | "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret); | 446 | "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret); |
447 | } | 447 | } |
448 | 448 | ||
449 | static int spcp8x5_carrier_raised(struct usb_serial_port *port) | ||
450 | { | ||
451 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | ||
452 | if (priv->line_status & MSR_STATUS_LINE_DCD) | ||
453 | return 1; | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on) | ||
458 | { | ||
459 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | ||
460 | unsigned long flags; | ||
461 | u8 control; | ||
462 | |||
463 | spin_lock_irqsave(&priv->lock, flags); | ||
464 | if (on) | ||
465 | priv->line_control = MCR_CONTROL_LINE_DTR | ||
466 | | MCR_CONTROL_LINE_RTS; | ||
467 | else | ||
468 | priv->line_control &= ~ (MCR_CONTROL_LINE_DTR | ||
469 | | MCR_CONTROL_LINE_RTS); | ||
470 | control = priv->line_control; | ||
471 | spin_unlock_irqrestore(&priv->lock, flags); | ||
472 | spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); | ||
473 | } | ||
474 | |||
449 | /* close the serial port. We should wait for data sending to device 1st and | 475 | /* close the serial port. We should wait for data sending to device 1st and |
450 | * then kill all urb. */ | 476 | * then kill all urb. */ |
451 | static void spcp8x5_close(struct tty_struct *tty, | 477 | static void spcp8x5_close(struct usb_serial_port *port) |
452 | struct usb_serial_port *port, struct file *filp) | ||
453 | { | 478 | { |
454 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | 479 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); |
455 | unsigned long flags; | 480 | unsigned long flags; |
456 | unsigned int c_cflag; | ||
457 | int bps; | ||
458 | long timeout; | ||
459 | wait_queue_t wait; | ||
460 | int result; | 481 | int result; |
461 | 482 | ||
462 | dbg("%s - port %d", __func__, port->number); | 483 | dbg("%s - port %d", __func__, port->number); |
463 | 484 | ||
464 | /* wait for data to drain from the buffer */ | ||
465 | spin_lock_irqsave(&priv->lock, flags); | 485 | spin_lock_irqsave(&priv->lock, flags); |
466 | timeout = SPCP8x5_CLOSING_WAIT; | ||
467 | init_waitqueue_entry(&wait, current); | ||
468 | add_wait_queue(&tty->write_wait, &wait); | ||
469 | for (;;) { | ||
470 | set_current_state(TASK_INTERRUPTIBLE); | ||
471 | if (ringbuf_avail_data(priv->buf) == 0 || | ||
472 | timeout == 0 || signal_pending(current)) | ||
473 | break; | ||
474 | spin_unlock_irqrestore(&priv->lock, flags); | ||
475 | timeout = schedule_timeout(timeout); | ||
476 | spin_lock_irqsave(&priv->lock, flags); | ||
477 | } | ||
478 | set_current_state(TASK_RUNNING); | ||
479 | remove_wait_queue(&tty->write_wait, &wait); | ||
480 | |||
481 | /* clear out any remaining data in the buffer */ | 486 | /* clear out any remaining data in the buffer */ |
482 | clear_ringbuf(priv->buf); | 487 | clear_ringbuf(priv->buf); |
483 | spin_unlock_irqrestore(&priv->lock, flags); | 488 | spin_unlock_irqrestore(&priv->lock, flags); |
484 | 489 | ||
485 | /* wait for characters to drain from the device (this is long enough | ||
486 | * for the entire all byte spcp8x5 hardware buffer to drain with no | ||
487 | * flow control for data rates of 1200 bps or more, for lower rates we | ||
488 | * should really know how much data is in the buffer to compute a delay | ||
489 | * that is not unnecessarily long) */ | ||
490 | bps = tty_get_baud_rate(tty); | ||
491 | if (bps > 1200) | ||
492 | timeout = max((HZ*2560) / bps, HZ/10); | ||
493 | else | ||
494 | timeout = 2*HZ; | ||
495 | set_current_state(TASK_INTERRUPTIBLE); | ||
496 | schedule_timeout(timeout); | ||
497 | |||
498 | /* clear control lines */ | ||
499 | if (tty) { | ||
500 | c_cflag = tty->termios->c_cflag; | ||
501 | if (c_cflag & HUPCL) { | ||
502 | spin_lock_irqsave(&priv->lock, flags); | ||
503 | priv->line_control = 0; | ||
504 | spin_unlock_irqrestore(&priv->lock, flags); | ||
505 | spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | /* kill urb */ | 490 | /* kill urb */ |
510 | if (port->write_urb != NULL) { | 491 | if (port->write_urb != NULL) { |
511 | result = usb_unlink_urb(port->write_urb); | 492 | result = usb_unlink_urb(port->write_urb); |
@@ -665,13 +646,6 @@ static int spcp8x5_open(struct tty_struct *tty, | |||
665 | if (ret) | 646 | if (ret) |
666 | return ret; | 647 | return ret; |
667 | 648 | ||
668 | spin_lock_irqsave(&priv->lock, flags); | ||
669 | if (tty && (tty->termios->c_cflag & CBAUD)) | ||
670 | priv->line_control = MCR_DTR | MCR_RTS; | ||
671 | else | ||
672 | priv->line_control = 0; | ||
673 | spin_unlock_irqrestore(&priv->lock, flags); | ||
674 | |||
675 | spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); | 649 | spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); |
676 | 650 | ||
677 | /* Setup termios */ | 651 | /* Setup termios */ |
@@ -691,9 +665,10 @@ static int spcp8x5_open(struct tty_struct *tty, | |||
691 | port->read_urb->dev = serial->dev; | 665 | port->read_urb->dev = serial->dev; |
692 | ret = usb_submit_urb(port->read_urb, GFP_KERNEL); | 666 | ret = usb_submit_urb(port->read_urb, GFP_KERNEL); |
693 | if (ret) { | 667 | if (ret) { |
694 | spcp8x5_close(tty, port, NULL); | 668 | spcp8x5_close(port); |
695 | return -EPROTO; | 669 | return -EPROTO; |
696 | } | 670 | } |
671 | port->port.drain_delay = 256; | ||
697 | return 0; | 672 | return 0; |
698 | } | 673 | } |
699 | 674 | ||
@@ -1033,6 +1008,8 @@ static struct usb_serial_driver spcp8x5_device = { | |||
1033 | .num_ports = 1, | 1008 | .num_ports = 1, |
1034 | .open = spcp8x5_open, | 1009 | .open = spcp8x5_open, |
1035 | .close = spcp8x5_close, | 1010 | .close = spcp8x5_close, |
1011 | .dtr_rts = spcp8x5_dtr_rts, | ||
1012 | .carrier_raised = spcp8x5_carrier_raised, | ||
1036 | .write = spcp8x5_write, | 1013 | .write = spcp8x5_write, |
1037 | .set_termios = spcp8x5_set_termios, | 1014 | .set_termios = spcp8x5_set_termios, |
1038 | .ioctl = spcp8x5_ioctl, | 1015 | .ioctl = spcp8x5_ioctl, |