static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,
struct ktermios *old_termios);
-static void __uart_wait_until_sent(struct uart_port *port, int timeout);
+static void uart_wait_until_sent(struct tty_struct *tty, int timeout);
static void uart_change_pm(struct uart_state *state, int pm_state);
/*
* closed. No cookie for you.
*/
BUG_ON(!state);
- tasklet_schedule(&state->tlet);
+ tty_wakeup(state->port.tty);
}
static void uart_stop(struct tty_struct *tty)
spin_unlock_irqrestore(&port->lock, flags);
}
-static void uart_tasklet_action(unsigned long data)
-{
- struct uart_state *state = (struct uart_state *)data;
- tty_wakeup(state->port.tty);
-}
-
static inline void
uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear)
{
}
/*
- * kill off our tasklet
+ * It's possible for shutdown to be called after suspend if we get
+ * a DCD drop (hangup) at just the right time. Clear suspended bit so
+ * we don't try to resume a port that has been shutdown.
*/
- tasklet_kill(&state->tlet);
+ clear_bit(ASYNCB_SUSPENDED, &port->flags);
/*
* Free the transmit buffer page.
struct uart_port *uport;
unsigned long flags;
- BUG_ON(!tty_locked());
-
if (!state)
return;
pr_debug("uart_close(%d) called\n", uport->line);
- mutex_lock(&port->mutex);
spin_lock_irqsave(&port->lock, flags);
if (tty_hung_up_p(filp)) {
spin_unlock_irqrestore(&port->lock, flags);
- goto done;
+ return;
}
if ((tty->count == 1) && (port->count != 1)) {
}
if (port->count) {
spin_unlock_irqrestore(&port->lock, flags);
- goto done;
+ return;
}
/*
* the line discipline to only process XON/XOFF characters by
* setting tty->closing.
*/
+ set_bit(ASYNCB_CLOSING, &port->flags);
tty->closing = 1;
spin_unlock_irqrestore(&port->lock, flags);
- 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);
- }
+ if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent_from_close(tty,
+ msecs_to_jiffies(port->closing_wait));
/*
* At this point, we stop accepting input. To do this, we
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
- __uart_wait_until_sent(uport, uport->timeout);
+ uart_wait_until_sent(tty, uport->timeout);
}
+ mutex_lock(&port->mutex);
uart_shutdown(tty, state);
uart_flush_buffer(tty);
* Wake up anyone trying to open this port.
*/
clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
+ clear_bit(ASYNCB_CLOSING, &port->flags);
spin_unlock_irqrestore(&port->lock, flags);
wake_up_interruptible(&port->open_wait);
+ wake_up_interruptible(&port->close_wait);
-done:
mutex_unlock(&port->mutex);
}
-static void __uart_wait_until_sent(struct uart_port *port, int timeout)
+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;
unsigned long char_time, expire;
if (port->type == PORT_UNKNOWN || port->fifosize == 0)
}
}
-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();
-}
-
/*
* This is called with the BKL held in
* linux/drivers/char/tty_io.c:do_tty_hangup()
struct tty_port *port = &state->port;
unsigned long flags;
- BUG_ON(!tty_locked());
pr_debug("uart_hangup(%d)\n", state->uart_port->line);
mutex_lock(&port->mutex);
struct tty_port *port;
int retval, line = tty->index;
- BUG_ON(!tty_locked());
pr_debug("uart_open(%d) called\n", line);
/*
if (port->tty && port->tty->termios && termios.c_cflag == 0)
termios = *(port->tty->termios);
+ if (console_suspend_enabled)
+ uart_change_pm(state, 0);
uport->ops->set_termios(uport, &termios, NULL);
if (console_suspend_enabled)
console_start(uport->cons);
case UPIO_MEM32:
case UPIO_AU:
case UPIO_TSI:
- case UPIO_DWAPB:
- case UPIO_DWAPB32:
snprintf(address, sizeof(address),
"MMIO 0x%llx", (unsigned long long)port->mapbase);
break;
port->ops = &uart_port_ops;
port->close_delay = 500; /* .5 seconds */
port->closing_wait = 30000; /* 30 seconds */
- tasklet_init(&state->tlet, uart_tasklet_action,
- (unsigned long)state);
}
retval = tty_register_driver(normal);
*/
uport->type = PORT_UNKNOWN;
- /*
- * Kill the tasklet, and free resources.
- */
- tasklet_kill(&state->tlet);
-
state->uart_port = NULL;
mutex_unlock(&port_mutex);
case UPIO_MEM32:
case UPIO_AU:
case UPIO_TSI:
- case UPIO_DWAPB:
- case UPIO_DWAPB32:
return (port1->mapbase == port2->mapbase);
}
return 0;