|
@@ -60,7 +60,7 @@ static struct lock_class_key port_lock_key;
|
|
|
|
|
|
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
|
|
static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
|
|
struct ktermios *old_termios);
|
|
struct ktermios *old_termios);
|
|
-static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
|
|
|
|
|
|
+static void __uart_wait_until_sent(struct uart_port *port, int timeout);
|
|
static void uart_change_pm(struct uart_state *state, int pm_state);
|
|
static void uart_change_pm(struct uart_state *state, int pm_state);
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1322,8 +1322,16 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
|
tty->closing = 1;
|
|
tty->closing = 1;
|
|
spin_unlock_irqrestore(&port->lock, flags);
|
|
spin_unlock_irqrestore(&port->lock, flags);
|
|
|
|
|
|
- if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
|
|
|
|
- tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait));
|
|
|
|
|
|
+ if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) {
|
|
|
|
+ /*
|
|
|
|
+ * hack: open-coded tty_wait_until_sent to avoid
|
|
|
|
+ * recursive tty_lock
|
|
|
|
+ */
|
|
|
|
+ long timeout = msecs_to_jiffies(port->closing_wait);
|
|
|
|
+ if (wait_event_interruptible_timeout(tty->write_wait,
|
|
|
|
+ !tty_chars_in_buffer(tty), timeout) >= 0)
|
|
|
|
+ __uart_wait_until_sent(uport, timeout);
|
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
/*
|
|
* At this point, we stop accepting input. To do this, we
|
|
* At this point, we stop accepting input. To do this, we
|
|
@@ -1339,7 +1347,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
|
|
* has completely drained; this is especially
|
|
* has completely drained; this is especially
|
|
* important if there is a transmit FIFO!
|
|
* important if there is a transmit FIFO!
|
|
*/
|
|
*/
|
|
- uart_wait_until_sent(tty, uport->timeout);
|
|
|
|
|
|
+ __uart_wait_until_sent(uport, uport->timeout);
|
|
}
|
|
}
|
|
|
|
|
|
uart_shutdown(tty, state);
|
|
uart_shutdown(tty, state);
|
|
@@ -1373,17 +1381,13 @@ done:
|
|
mutex_unlock(&port->mutex);
|
|
mutex_unlock(&port->mutex);
|
|
}
|
|
}
|
|
|
|
|
|
-static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
|
|
|
|
|
|
+static void __uart_wait_until_sent(struct uart_port *port, int timeout)
|
|
{
|
|
{
|
|
- struct uart_state *state = tty->driver_data;
|
|
|
|
- struct uart_port *port = state->uart_port;
|
|
|
|
unsigned long char_time, expire;
|
|
unsigned long char_time, expire;
|
|
|
|
|
|
if (port->type == PORT_UNKNOWN || port->fifosize == 0)
|
|
if (port->type == PORT_UNKNOWN || port->fifosize == 0)
|
|
return;
|
|
return;
|
|
|
|
|
|
- tty_lock_nested(); /* already locked when coming from close */
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Set the check interval to be 1/5 of the estimated time to
|
|
* Set the check interval to be 1/5 of the estimated time to
|
|
* send a single character, and make it at least 1. The check
|
|
* send a single character, and make it at least 1. The check
|
|
@@ -1429,6 +1433,15 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
set_current_state(TASK_RUNNING); /* might not be needed */
|
|
set_current_state(TASK_RUNNING); /* might not be needed */
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
|
|
|
|
+{
|
|
|
|
+ struct uart_state *state = tty->driver_data;
|
|
|
|
+ struct uart_port *port = state->uart_port;
|
|
|
|
+
|
|
|
|
+ tty_lock();
|
|
|
|
+ __uart_wait_until_sent(port, timeout);
|
|
tty_unlock();
|
|
tty_unlock();
|
|
}
|
|
}
|
|
|
|
|