diff options
Diffstat (limited to 'drivers/usb/serial/io_ti.c')
-rw-r--r-- | drivers/usb/serial/io_ti.c | 89 |
1 files changed, 22 insertions, 67 deletions
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 82afc4d6a327..641ab3da2d83 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -521,65 +521,6 @@ exit_is_tx_active: return bytes_left; } -static void chase_port(struct edgeport_port *port, unsigned long timeout, - int flush) -{ - int baud_rate; - struct tty_struct *tty = tty_port_tty_get(&port->port->port); - struct usb_serial *serial = port->port->serial; - wait_queue_t wait; - unsigned long flags; - - if (!tty) - return; - - if (!timeout) - timeout = (HZ * EDGE_CLOSING_WAIT)/100; - - /* wait for data to drain from the buffer */ - spin_lock_irqsave(&port->ep_lock, flags); - init_waitqueue_entry(&wait, current); - add_wait_queue(&tty->write_wait, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (kfifo_len(&port->write_fifo) == 0 - || timeout == 0 || signal_pending(current) - || serial->disconnected) - /* disconnect */ - break; - spin_unlock_irqrestore(&port->ep_lock, flags); - timeout = schedule_timeout(timeout); - spin_lock_irqsave(&port->ep_lock, flags); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&tty->write_wait, &wait); - if (flush) - kfifo_reset_out(&port->write_fifo); - spin_unlock_irqrestore(&port->ep_lock, flags); - tty_kref_put(tty); - - /* wait for data to drain from the device */ - timeout += jiffies; - while ((long)(jiffies - timeout) < 0 && !signal_pending(current) - && !serial->disconnected) { - /* not disconnected */ - if (!tx_active(port)) - break; - msleep(10); - } - - /* disconnected */ - if (serial->disconnected) - return; - - /* wait one more character time, based on baud rate */ - /* (tx_active doesn't seem to wait for the last byte) */ - baud_rate = port->baud_rate; - if (baud_rate == 0) - baud_rate = 50; - msleep(max(1, DIV_ROUND_UP(10000, baud_rate))); -} - static int choose_config(struct usb_device *dev) { /* @@ -1944,6 +1885,8 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) ++edge_serial->num_ports_open; + port->port.drain_delay = 1; + goto release_es_lock; unlink_int_urb: @@ -1959,6 +1902,7 @@ static void edge_close(struct usb_serial_port *port) struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; struct usb_serial *serial = port->serial; + unsigned long flags; int port_number; edge_serial = usb_get_serial_data(port->serial); @@ -1970,12 +1914,12 @@ static void edge_close(struct usb_serial_port *port) * this flag and dump add read data */ edge_port->close_pending = 1; - /* chase the port close and flush */ - chase_port(edge_port, (HZ * closing_wait) / 100, 1); - usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); edge_port->ep_write_urb_in_use = 0; + spin_lock_irqsave(&edge_port->ep_lock, flags); + kfifo_reset_out(&edge_port->write_fifo); + spin_unlock_irqrestore(&edge_port->ep_lock, flags); /* assuming we can still talk to the device, * send a close port command to it */ @@ -2101,16 +2045,21 @@ static int edge_chars_in_buffer(struct tty_struct *tty) struct edgeport_port *edge_port = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; + int ret; if (edge_port == NULL) return 0; - if (edge_port->close_pending == 1) - return 0; spin_lock_irqsave(&edge_port->ep_lock, flags); chars = kfifo_len(&edge_port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); + if (!chars) { + ret = tx_active(edge_port); + if (ret > 0) + chars = ret; + } + dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } @@ -2448,10 +2397,15 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct __user *retinfo) { struct serial_struct tmp; + unsigned cwait; if (!retinfo) return -EFAULT; + cwait = edge_port->port->port.closing_wait; + if (cwait != ASYNC_CLOSING_WAIT_NONE) + cwait = jiffies_to_msecs(closing_wait) / 10; + memset(&tmp, 0, sizeof(tmp)); tmp.type = PORT_16550A; @@ -2462,7 +2416,7 @@ static int get_serial_info(struct edgeport_port *edge_port, tmp.xmit_fifo_size = edge_port->port->bulk_out_size; tmp.baud_base = 9600; tmp.close_delay = 5*HZ; - tmp.closing_wait = closing_wait; + tmp.closing_wait = cwait; if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) return -EFAULT; @@ -2517,8 +2471,7 @@ static void edge_break(struct tty_struct *tty, int break_state) int status; int bv = 0; /* Off */ - /* chase the port close */ - chase_port(edge_port, 0, 0); + tty_wait_until_sent(tty, 0); if (break_state == -1) bv = 1; /* On */ @@ -2591,6 +2544,8 @@ static int edge_port_probe(struct usb_serial_port *port) return ret; } + port->port.closing_wait = msecs_to_jiffies(closing_wait * 10); + return 0; } |