From 783ca3557b83b915d1b7a47240e7ab6acca0aac8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:33 +0100 Subject: USB: ti_usb_3410_5052: switch to generic get_icount implementation Switch to the generic get_icount implementation. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 44 ++++++----------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) (limited to 'drivers/usb/serial/ti_usb_3410_5052.c') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 73deb029fc05..999772538374 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -73,7 +73,6 @@ struct ti_port { unsigned int tp_uart_base_addr; int tp_flags; int tp_closing_wait;/* in .01 secs */ - struct async_icount tp_icount; wait_queue_head_t tp_write_wait; struct ti_device *tp_tdev; struct usb_serial_port *tp_port; @@ -108,8 +107,6 @@ static void ti_throttle(struct tty_struct *tty); static void ti_unthrottle(struct tty_struct *tty); static int ti_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); -static int ti_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount); static void ti_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios); static int ti_tiocmget(struct tty_struct *tty); @@ -235,7 +232,7 @@ static struct usb_serial_driver ti_1port_device = { .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, - .get_icount = ti_get_icount, + .get_icount = usb_serial_generic_get_icount, .break_ctl = ti_break, .read_int_callback = ti_interrupt_callback, .read_bulk_callback = ti_bulk_in_callback, @@ -265,7 +262,7 @@ static struct usb_serial_driver ti_2port_device = { .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, - .get_icount = ti_get_icount, + .get_icount = usb_serial_generic_get_icount, .break_ctl = ti_break, .read_int_callback = ti_interrupt_callback, .read_bulk_callback = ti_bulk_in_callback, @@ -480,8 +477,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) port_number = port->number - port->serial->minor; - memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount)); - tport->tp_msr = 0; tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR); @@ -731,31 +726,6 @@ static void ti_unthrottle(struct tty_struct *tty) } } -static int ti_get_icount(struct tty_struct *tty, - struct serial_icounter_struct *icount) -{ - struct usb_serial_port *port = tty->driver_data; - struct ti_port *tport = usb_get_serial_port_data(port); - struct async_icount cnow = tport->tp_icount; - - dev_dbg(&port->dev, "%s - TIOCGICOUNT RX=%d, TX=%d\n", __func__, - cnow.rx, cnow.tx); - - icount->cts = cnow.cts; - icount->dsr = cnow.dsr; - icount->rng = cnow.rng; - icount->dcd = cnow.dcd; - icount->rx = cnow.rx; - icount->tx = cnow.tx; - icount->frame = cnow.frame; - icount->overrun = cnow.overrun; - icount->parity = cnow.parity; - icount->brk = cnow.brk; - icount->buf_overrun = cnow.buf_overrun; - - return 0; -} - static int ti_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -780,7 +750,7 @@ static int ti_ioctl(struct tty_struct *tty, (struct serial_struct __user *)arg); case TIOCMIWAIT: dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); - cprev = tport->tp_icount; + cprev = port->icount; while (1) { interruptible_sleep_on(&port->delta_msr_wait); if (signal_pending(current)) @@ -789,7 +759,7 @@ static int ti_ioctl(struct tty_struct *tty, if (port->serial->disconnected) return -EIO; - cnow = tport->tp_icount; + cnow = port->icount; if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) return -EIO; /* no change => error */ @@ -1156,7 +1126,7 @@ static void ti_bulk_in_callback(struct urb *urb) else ti_recv(port, urb->transfer_buffer, urb->actual_length); spin_lock(&tport->tp_lock); - tport->tp_icount.rx += urb->actual_length; + port->icount.rx += urb->actual_length; spin_unlock(&tport->tp_lock); } @@ -1265,7 +1235,7 @@ static void ti_send(struct ti_port *tport) /* TODO: reschedule ti_send */ } else { spin_lock_irqsave(&tport->tp_lock, flags); - tport->tp_icount.tx += count; + port->icount.tx += count; spin_unlock_irqrestore(&tport->tp_lock, flags); } @@ -1385,7 +1355,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) if (msr & TI_MSR_DELTA_MASK) { spin_lock_irqsave(&tport->tp_lock, flags); - icount = &tport->tp_icount; + icount = &tport->tp_port->icount; if (msr & TI_MSR_DELTA_CTS) icount->cts++; if (msr & TI_MSR_DELTA_DSR) -- cgit v1.2.2 From 6c75e26067c8b8a17aea1bb54b9a8dc9d229c5e8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 21 Mar 2013 12:37:34 +0100 Subject: USB: ti_usb_3410_5052: switch to generic TIOCMIWAIT implementation Switch to the generic TIOCMIWAIT implementation which does not suffer from the races involved when using the deprecated sleep_on functions. This also fixes the issue with processes waiting for modem-status-changes not being woken up at disconnect. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) (limited to 'drivers/usb/serial/ti_usb_3410_5052.c') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 999772538374..07268591b0d1 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -232,6 +232,7 @@ static struct usb_serial_driver ti_1port_device = { .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .break_ctl = ti_break, .read_int_callback = ti_interrupt_callback, @@ -262,6 +263,7 @@ static struct usb_serial_driver ti_2port_device = { .set_termios = ti_set_termios, .tiocmget = ti_tiocmget, .tiocmset = ti_tiocmset, + .tiocmiwait = usb_serial_generic_tiocmiwait, .get_icount = usb_serial_generic_get_icount, .break_ctl = ti_break, .read_int_callback = ti_interrupt_callback, @@ -731,8 +733,6 @@ static int ti_ioctl(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; struct ti_port *tport = usb_get_serial_port_data(port); - struct async_icount cnow; - struct async_icount cprev; dev_dbg(&port->dev, "%s - cmd = 0x%04X\n", __func__, cmd); @@ -748,29 +748,6 @@ static int ti_ioctl(struct tty_struct *tty, dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__); return ti_set_serial_info(tty, tport, (struct serial_struct __user *)arg); - case TIOCMIWAIT: - dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); - cprev = port->icount; - while (1) { - interruptible_sleep_on(&port->delta_msr_wait); - if (signal_pending(current)) - return -ERESTARTSYS; - - if (port->serial->disconnected) - return -EIO; - - cnow = port->icount; - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) - return 0; - cprev = cnow; - } - break; } return -ENOIOCTLCMD; } @@ -1364,7 +1341,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) icount->dcd++; if (msr & TI_MSR_DELTA_RI) icount->rng++; - wake_up_interruptible(&tport->tp_port->delta_msr_wait); + wake_up_interruptible(&tport->tp_port->port.delta_msr_wait); spin_unlock_irqrestore(&tport->tp_lock, flags); } -- cgit v1.2.2 From 113ec31e16afe197a668d4b63ce41e04dc706c64 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:19 +0200 Subject: USB: ti_usb_3410_5052: move write-fifo flushing to close Move write-fifo flushing from ti_drain to close where it belongs. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/usb/serial/ti_usb_3410_5052.c') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 07268591b0d1..a49d2a746ccf 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -128,7 +128,7 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, struct serial_struct __user *new_arg); static void ti_handle_new_msr(struct ti_port *tport, __u8 msr); -static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush); +static void ti_drain(struct ti_port *tport, unsigned long timeout); static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty); static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty); @@ -601,6 +601,7 @@ static void ti_close(struct usb_serial_port *port) int port_number; int status; int do_unlock; + unsigned long flags; tdev = usb_get_serial_data(port->serial); tport = usb_get_serial_port_data(port); @@ -609,11 +610,14 @@ static void ti_close(struct usb_serial_port *port) tport->tp_is_open = 0; - ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1); + ti_drain(tport, (tport->tp_closing_wait*HZ)/100); usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); tport->tp_write_urb_in_use = 0; + spin_lock_irqsave(&tport->tp_lock, flags); + kfifo_reset_out(&tport->write_fifo); + spin_unlock_irqrestore(&tport->tp_lock, flags); port_number = port->number - port->serial->minor; @@ -965,7 +969,7 @@ static void ti_break(struct tty_struct *tty, int break_state) if (tport == NULL) return; - ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0); + ti_drain(tport, (tport->tp_closing_wait*HZ)/100); status = ti_write_byte(port, tport->tp_tdev, tport->tp_uart_base_addr + TI_UART_OFFSET_LCR, @@ -1361,7 +1365,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) } -static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush) +static void ti_drain(struct ti_port *tport, unsigned long timeout) { struct ti_device *tdev = tport->tp_tdev; struct usb_serial_port *port = tport->tp_port; @@ -1386,11 +1390,6 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush) } set_current_state(TASK_RUNNING); remove_wait_queue(&tport->tp_write_wait, &wait); - - /* flush any remaining data in the buffer */ - if (flush) - kfifo_reset_out(&tport->write_fifo); - spin_unlock_irq(&tport->tp_lock); mutex_lock(&port->serial->disc_mutex); -- cgit v1.2.2 From b5784f7d8528926d69c5868f1ddb2af99f85e799 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:20 +0200 Subject: USB: ti_usb_3410_5052: remove lsr from port data The line status register is only polled so let's not keep a possibly outdated value in the port data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/usb/serial/ti_usb_3410_5052.c') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index a49d2a746ccf..3ed8ecafe597 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -67,7 +67,6 @@ struct ti_port { int tp_is_open; __u8 tp_msr; - __u8 tp_lsr; __u8 tp_shadow_mcr; __u8 tp_uart_mode; /* 232 or 485 modes */ unsigned int tp_uart_base_addr; @@ -121,7 +120,7 @@ static void ti_recv(struct usb_serial_port *port, unsigned char *data, int length); static void ti_send(struct ti_port *tport); static int ti_set_mcr(struct ti_port *tport, unsigned int mcr); -static int ti_get_lsr(struct ti_port *tport); +static int ti_get_lsr(struct ti_port *tport, u8 *lsr); static int ti_get_serial_info(struct ti_port *tport, struct serial_struct __user *ret_arg); static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, @@ -1251,7 +1250,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr) } -static int ti_get_lsr(struct ti_port *tport) +static int ti_get_lsr(struct ti_port *tport, u8 *lsr) { int size, status; struct ti_device *tdev = tport->tp_tdev; @@ -1277,7 +1276,7 @@ static int ti_get_lsr(struct ti_port *tport) dev_dbg(&port->dev, "%s - lsr 0x%02X\n", __func__, data->bLSR); - tport->tp_lsr = data->bLSR; + *lsr = data->bLSR; free_data: kfree(data); @@ -1370,6 +1369,7 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout) struct ti_device *tdev = tport->tp_tdev; struct usb_serial_port *port = tport->tp_port; wait_queue_t wait; + u8 lsr; spin_lock_irq(&tport->tp_lock); @@ -1396,11 +1396,11 @@ static void ti_drain(struct ti_port *tport, unsigned long timeout) /* wait for data to drain from the device */ /* wait for empty tx register, plus 20 ms */ timeout += jiffies; - tport->tp_lsr &= ~TI_LSR_TX_EMPTY; + lsr = 0; while ((long)(jiffies - timeout) < 0 && !signal_pending(current) - && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error + && !(lsr & TI_LSR_TX_EMPTY) && !tdev->td_urb_error && !port->serial->disconnected) { - if (ti_get_lsr(tport)) + if (ti_get_lsr(tport, &lsr)) break; mutex_unlock(&port->serial->disc_mutex); msleep_interruptible(20); -- cgit v1.2.2 From 2c992cd73772bd0ef107536e8e3399d28493caa8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:21 +0200 Subject: USB: ti_usb_3410_5052: query hardware-buffer status in chars_in_buffer Query hardware-buffer status in chars_in_buffer should the write fifo be empty. This is needed to make the tty layer wait for hardware buffers to drain on close. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/usb/serial/ti_usb_3410_5052.c') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 3ed8ecafe597..062b6d872ea3 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -687,6 +687,8 @@ static int ti_chars_in_buffer(struct tty_struct *tty) struct ti_port *tport = usb_get_serial_port_data(port); int chars = 0; unsigned long flags; + int ret; + u8 lsr; if (tport == NULL) return 0; @@ -695,6 +697,12 @@ static int ti_chars_in_buffer(struct tty_struct *tty) chars = kfifo_len(&tport->write_fifo); spin_unlock_irqrestore(&tport->tp_lock, flags); + if (!chars) { + ret = ti_get_lsr(tport, &lsr); + if (!ret && !(lsr & TI_LSR_TX_EMPTY)) + chars = 1; + } + dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } -- cgit v1.2.2 From c0419024332a73f299bdd7a6875a00cf3942a054 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:22 +0200 Subject: USB: ti_usb_3410_5052: remove redundant drain from break_ctl Remove redundant drain, which has already been handled by the tty-layer, from break_ctl. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/usb/serial/ti_usb_3410_5052.c') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 062b6d872ea3..6a40823e85c4 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -976,8 +976,6 @@ static void ti_break(struct tty_struct *tty, int break_state) if (tport == NULL) return; - ti_drain(tport, (tport->tp_closing_wait*HZ)/100); - status = ti_write_byte(port, tport->tp_tdev, tport->tp_uart_base_addr + TI_UART_OFFSET_LCR, TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0); -- cgit v1.2.2 From f1175daa5312dd1b3f5940413c7c41ed195066f7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Apr 2013 17:33:23 +0200 Subject: USB: ti_usb_3410_5052: kill custom closing_wait Kill custom closing_wait implementation and let the tty-layer handle it instead. Note that the port drain-delay is set to three characters to keep the 20ms delay after wait_until_sent at low baudrates (1200 baud) during close. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 69 ++++++++--------------------------- 1 file changed, 15 insertions(+), 54 deletions(-) (limited to 'drivers/usb/serial/ti_usb_3410_5052.c') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 6a40823e85c4..4b52132812c1 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -71,7 +71,6 @@ struct ti_port { __u8 tp_uart_mode; /* 232 or 485 modes */ unsigned int tp_uart_base_addr; int tp_flags; - int tp_closing_wait;/* in .01 secs */ wait_queue_head_t tp_write_wait; struct ti_device *tp_tdev; struct usb_serial_port *tp_port; @@ -127,8 +126,6 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, struct serial_struct __user *new_arg); static void ti_handle_new_msr(struct ti_port *tport, __u8 msr); -static void ti_drain(struct ti_port *tport, unsigned long timeout); - static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty); static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty); @@ -428,7 +425,7 @@ static int ti_port_probe(struct usb_serial_port *port) tport->tp_uart_base_addr = TI_UART1_BASE_ADDR; else tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; - tport->tp_closing_wait = closing_wait; + port->port.closing_wait = msecs_to_jiffies(10 * closing_wait); init_waitqueue_head(&tport->tp_write_wait); if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) { kfree(tport); @@ -581,6 +578,8 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) tport->tp_is_open = 1; ++tdev->td_open_port_count; + port->port.drain_delay = 3; + goto release_lock; unlink_int_urb: @@ -609,8 +608,6 @@ static void ti_close(struct usb_serial_port *port) tport->tp_is_open = 0; - ti_drain(tport, (tport->tp_closing_wait*HZ)/100); - usb_kill_urb(port->read_urb); usb_kill_urb(port->write_urb); tport->tp_write_urb_in_use = 0; @@ -1295,10 +1292,15 @@ static int ti_get_serial_info(struct ti_port *tport, { struct usb_serial_port *port = tport->tp_port; struct serial_struct ret_serial; + unsigned cwait; if (!ret_arg) return -EFAULT; + cwait = port->port.closing_wait; + if (cwait != ASYNC_CLOSING_WAIT_NONE) + cwait = jiffies_to_msecs(cwait) / 10; + memset(&ret_serial, 0, sizeof(ret_serial)); ret_serial.type = PORT_16550A; @@ -1307,7 +1309,7 @@ static int ti_get_serial_info(struct ti_port *tport, ret_serial.flags = tport->tp_flags; ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE; ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800; - ret_serial.closing_wait = tport->tp_closing_wait; + ret_serial.closing_wait = cwait; if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg))) return -EFAULT; @@ -1320,12 +1322,17 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, struct serial_struct __user *new_arg) { struct serial_struct new_serial; + unsigned cwait; if (copy_from_user(&new_serial, new_arg, sizeof(new_serial))) return -EFAULT; + cwait = new_serial.closing_wait; + if (cwait != ASYNC_CLOSING_WAIT_NONE) + cwait = msecs_to_jiffies(10 * new_serial.closing_wait); + tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; - tport->tp_closing_wait = new_serial.closing_wait; + tport->tp_port->port.closing_wait = cwait; return 0; } @@ -1370,52 +1377,6 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) } -static void ti_drain(struct ti_port *tport, unsigned long timeout) -{ - struct ti_device *tdev = tport->tp_tdev; - struct usb_serial_port *port = tport->tp_port; - wait_queue_t wait; - u8 lsr; - - spin_lock_irq(&tport->tp_lock); - - /* wait for data to drain from the buffer */ - tdev->td_urb_error = 0; - init_waitqueue_entry(&wait, current); - add_wait_queue(&tport->tp_write_wait, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (kfifo_len(&tport->write_fifo) == 0 - || timeout == 0 || signal_pending(current) - || tdev->td_urb_error - || port->serial->disconnected) /* disconnect */ - break; - spin_unlock_irq(&tport->tp_lock); - timeout = schedule_timeout(timeout); - spin_lock_irq(&tport->tp_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&tport->tp_write_wait, &wait); - spin_unlock_irq(&tport->tp_lock); - - mutex_lock(&port->serial->disc_mutex); - /* wait for data to drain from the device */ - /* wait for empty tx register, plus 20 ms */ - timeout += jiffies; - lsr = 0; - while ((long)(jiffies - timeout) < 0 && !signal_pending(current) - && !(lsr & TI_LSR_TX_EMPTY) && !tdev->td_urb_error - && !port->serial->disconnected) { - if (ti_get_lsr(tport, &lsr)) - break; - mutex_unlock(&port->serial->disc_mutex); - msleep_interruptible(20); - mutex_lock(&port->serial->disc_mutex); - } - mutex_unlock(&port->serial->disc_mutex); -} - - static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty) { unsigned long flags; -- cgit v1.2.2