summaryrefslogtreecommitdiff
path: root/drivers/tty
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-08 06:52:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-08 06:52:11 -0400
commit683a52a10148e929fb4844f9237f059a47c0b01b (patch)
treea64af13ef46a08ff12d1974725cd70d768750fb6 /drivers/tty
parentb9af5643fdc5365a23f9752a1181fef374425217 (diff)
parent69784fa539efa477f39b5a849c27d5e630e0db27 (diff)
downloadlinux-683a52a10148e929fb4844f9237f059a47c0b01b.tar.gz
linux-683a52a10148e929fb4844f9237f059a47c0b01b.tar.bz2
linux-683a52a10148e929fb4844f9237f059a47c0b01b.zip
Merge tag 'tty-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here's the big tty/serial driver patchset for 3.18-rc1. Lots of little things in here, some good work from Peter Hurley on the tty core, and in lots of drivers. There are also lots of other driver updates in here as well, full details in the changelogs. All have been in the linux-next tree for a while" * tag 'tty-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (99 commits) Revert "serial/core: Initialize the console pm state" tty: serial: 8250: use 32bit variable for rpm_tx_active tty: serial: msm: Add earlycon support serial/core: Initialize the console pm state serial: asc: Conditionally use readl_relaxed (COMPILE_TEST) serial: of-serial: add PM suspend/resume support m68k: AMIGA_BUILTIN_SERIAL should depend on TTY asm/uapi: Add definition of TIOC[SG]RS485 tty/metag_da: Add console_poll module parameter serial: 8250_pci: remove rts_n override from Baytrail quirk serial: cadence: Add generic earlycon support serial: imx: change the wait even to interruptiable serial: imx: terminate the RX DMA when the UART is suspending serial: imx: fix throttle/unthrottle callbacks for hardware assisted flow control serial: 8250: Add Quark X1000 to 8250_pci.c tty: omap-serial: pull out calculation from baud_is_mode16 tty: omap-serial: fix division by zero xen_hvc: no reason to write the type key on xenstore tty: serial: 8250_core: remove UART_IER_RDI in serial8250_stop_rx() tty: serial: 8250_core: use the ->line argument as a hint in serial8250_find_match_or_unused() ...
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/hvc/hvc_xen.c3
-rw-r--r--drivers/tty/metag_da.c14
-rw-r--r--drivers/tty/moxa.c2
-rw-r--r--drivers/tty/n_tty.c8
-rw-r--r--drivers/tty/nozomi.c6
-rw-r--r--drivers/tty/pty.c41
-rw-r--r--drivers/tty/serial/8250/8250.h3
-rw-r--r--drivers/tty/serial/8250/8250_core.c253
-rw-r--r--drivers/tty/serial/8250/8250_fintek.c249
-rw-r--r--drivers/tty/serial/8250/8250_hp300.c2
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c294
-rw-r--r--drivers/tty/serial/8250/8250_pci.c34
-rw-r--r--drivers/tty/serial/8250/Kconfig15
-rw-r--r--drivers/tty/serial/8250/Makefile2
-rw-r--r--drivers/tty/serial/Kconfig23
-rw-r--r--drivers/tty/serial/Makefile1
-rw-r--r--drivers/tty/serial/altera_jtaguart.c2
-rw-r--r--drivers/tty/serial/altera_uart.c2
-rw-r--r--drivers/tty/serial/amba-pl011.c54
-rw-r--r--drivers/tty/serial/bfin_sport_uart.c1
-rw-r--r--drivers/tty/serial/bfin_uart.c15
-rw-r--r--drivers/tty/serial/clps711x.c32
-rw-r--r--drivers/tty/serial/imx.c99
-rw-r--r--drivers/tty/serial/jsm/jsm.h10
-rw-r--r--drivers/tty/serial/jsm/jsm_driver.c38
-rw-r--r--drivers/tty/serial/kgdb_nmi.c5
-rw-r--r--drivers/tty/serial/meson_uart.c634
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c17
-rw-r--r--drivers/tty/serial/msm_serial.c122
-rw-r--r--drivers/tty/serial/mxs-auart.c2
-rw-r--r--drivers/tty/serial/nwpserial.c1
-rw-r--r--drivers/tty/serial/of_serial.c31
-rw-r--r--drivers/tty/serial/omap-serial.c34
-rw-r--r--drivers/tty/serial/serial_core.c135
-rw-r--r--drivers/tty/serial/serial_mctrl_gpio.c2
-rw-r--r--drivers/tty/serial/st-asc.c8
-rw-r--r--drivers/tty/serial/sunhv.c3
-rw-r--r--drivers/tty/serial/sunsab.c5
-rw-r--r--drivers/tty/serial/uartlite.c1
-rw-r--r--drivers/tty/serial/vr41xx_siu.c1
-rw-r--r--drivers/tty/serial/vt8500_serial.c136
-rw-r--r--drivers/tty/serial/xilinx_uartps.c20
-rw-r--r--drivers/tty/tty_io.c96
-rw-r--r--drivers/tty/tty_ioctl.c49
-rw-r--r--drivers/tty/vt/keyboard.c166
45 files changed, 2183 insertions, 488 deletions
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index 2dc2831840ca..2967f0388d2c 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -402,9 +402,6 @@ static int xencons_connect_backend(struct xenbus_device *dev,
evtchn);
if (ret)
goto error_xenbus;
- ret = xenbus_printf(xbt, dev->nodename, "type", "ioemu");
- if (ret)
- goto error_xenbus;
ret = xenbus_transaction_end(xbt, 0);
if (ret) {
if (ret == -EAGAIN)
diff --git a/drivers/tty/metag_da.c b/drivers/tty/metag_da.c
index 7332e2ca4615..3774600741d8 100644
--- a/drivers/tty/metag_da.c
+++ b/drivers/tty/metag_da.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
+#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/serial.h>
@@ -70,6 +71,15 @@ static struct tty_driver *channel_driver;
static struct timer_list put_timer;
static struct task_struct *dashtty_thread;
+/*
+ * The console_poll parameter determines whether the console channel should be
+ * polled for input.
+ * By default the console channel isn't polled at all, in order to avoid the
+ * overhead, but that means it isn't possible to have a login on /dev/console.
+ */
+static bool console_poll;
+module_param(console_poll, bool, S_IRUGO);
+
#define RX_BUF_SIZE 1024
enum {
@@ -353,7 +363,7 @@ static int dashtty_port_activate(struct tty_port *port, struct tty_struct *tty)
* possible to have a login on /dev/console.
*
*/
- if (dport != &dashtty_ports[CONSOLE_CHANNEL])
+ if (console_poll || dport != &dashtty_ports[CONSOLE_CHANNEL])
if (atomic_inc_return(&num_channels_need_poll) == 1)
add_poll_timer(&poll_timer);
@@ -372,7 +382,7 @@ static void dashtty_port_shutdown(struct tty_port *port)
unsigned int count;
/* stop reading */
- if (dport != &dashtty_ports[CONSOLE_CHANNEL])
+ if (console_poll || dport != &dashtty_ports[CONSOLE_CHANNEL])
if (atomic_dec_and_test(&num_channels_need_poll))
del_timer_sync(&poll_timer);
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index 1deaca4674e4..14c54e041065 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -1096,7 +1096,7 @@ static int __init moxa_init(void)
continue;
}
- printk(KERN_INFO "MOXA isa board found at 0x%.8lu and "
+ printk(KERN_INFO "MOXA isa board found at 0x%.8lx and "
"ready (%u ports, firmware loaded)\n",
baseaddr[i], brd->numPorts);
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index f44f1ba762c3..89c4cee253e3 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1166,7 +1166,7 @@ static void n_tty_receive_break(struct tty_struct *tty)
}
put_tty_queue('\0', ldata);
if (waitqueue_active(&tty->read_wait))
- wake_up_interruptible(&tty->read_wait);
+ wake_up_interruptible_poll(&tty->read_wait, POLLIN);
}
/**
@@ -1226,7 +1226,7 @@ static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c)
} else
put_tty_queue(c, ldata);
if (waitqueue_active(&tty->read_wait))
- wake_up_interruptible(&tty->read_wait);
+ wake_up_interruptible_poll(&tty->read_wait, POLLIN);
}
static void
@@ -1378,7 +1378,7 @@ handle_newline:
ldata->canon_head = ldata->read_head;
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
- wake_up_interruptible(&tty->read_wait);
+ wake_up_interruptible_poll(&tty->read_wait, POLLIN);
return 0;
}
}
@@ -1679,7 +1679,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
L_EXTPROC(tty)) {
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
- wake_up_interruptible(&tty->read_wait);
+ wake_up_interruptible_poll(&tty->read_wait, POLLIN);
}
}
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
index cd0429369557..74885af8c7bd 100644
--- a/drivers/tty/nozomi.c
+++ b/drivers/tty/nozomi.c
@@ -523,7 +523,7 @@ static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf,
}
/* Setup pointers to different channels and also setup buffer sizes. */
-static void setup_memory(struct nozomi *dc)
+static void nozomi_setup_memory(struct nozomi *dc)
{
void __iomem *offset = dc->base_addr + dc->config_table.dl_start;
/* The length reported is including the length field of 4 bytes,
@@ -671,7 +671,7 @@ static int nozomi_read_config_table(struct nozomi *dc)
int i;
DBG1("Second phase, configuring card");
- setup_memory(dc);
+ nozomi_setup_memory(dc);
dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul;
dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl;
@@ -705,7 +705,7 @@ static int nozomi_read_config_table(struct nozomi *dc)
dc->config_table.version);
/* Here we should disable all I/O over F32. */
- setup_memory(dc);
+ nozomi_setup_memory(dc);
/*
* We should send ALL channel pair tokens back along
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 9bbdb1de12e2..7c4447a5c0f4 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -24,6 +24,7 @@
#include <linux/devpts_fs.h>
#include <linux/slab.h>
#include <linux/mutex.h>
+#include <linux/poll.h>
#ifdef CONFIG_UNIX98_PTYS
@@ -313,6 +314,42 @@ done:
}
/**
+ * pty_start - start() handler
+ * pty_stop - stop() handler
+ * @tty: tty being flow-controlled
+ *
+ * Propagates the TIOCPKT status to the master pty.
+ *
+ * NB: only the master pty can be in packet mode so only the slave
+ * needs start()/stop() handlers
+ */
+static void pty_start(struct tty_struct *tty)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ if (tty->link && tty->link->packet) {
+ tty->ctrl_status &= ~TIOCPKT_STOP;
+ tty->ctrl_status |= TIOCPKT_START;
+ wake_up_interruptible_poll(&tty->link->read_wait, POLLIN);
+ }
+ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+}
+
+static void pty_stop(struct tty_struct *tty)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tty->ctrl_lock, flags);
+ if (tty->link && tty->link->packet) {
+ tty->ctrl_status &= ~TIOCPKT_START;
+ tty->ctrl_status |= TIOCPKT_STOP;
+ wake_up_interruptible_poll(&tty->link->read_wait, POLLIN);
+ }
+ spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+}
+
+/**
* pty_common_install - set up the pty pair
* @driver: the pty driver
* @tty: the tty being instantiated
@@ -471,6 +508,8 @@ static const struct tty_operations slave_pty_ops_bsd = {
.set_termios = pty_set_termios,
.cleanup = pty_cleanup,
.resize = pty_resize,
+ .start = pty_start,
+ .stop = pty_stop,
.remove = pty_remove
};
@@ -646,6 +685,8 @@ static const struct tty_operations pty_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
+ .start = pty_start,
+ .stop = pty_stop,
.shutdown = pty_unix98_shutdown,
.cleanup = pty_cleanup,
};
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 1b08c918cd51..1bcb4b2141a6 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -72,6 +72,7 @@ struct serial8250_config {
#define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */
#define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */
#define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */
+#define UART_CAP_RPM (1 << 15) /* Runtime PM is active while idle */
#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
@@ -112,6 +113,8 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
up->dl_write(up, value);
}
+struct uart_8250_port *serial8250_get_port(int line);
+
#if defined(__alpha__) && !defined(CONFIG_PCI)
/*
* Digital did something really horribly wrong with the OUT1 and OUT2
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index bd672948f2f1..ca5cfdc1459a 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -37,6 +37,8 @@
#include <linux/nmi.h>
#include <linux/mutex.h>
#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
#ifdef CONFIG_SPARC
#include <linux/sunserialcore.h>
#endif
@@ -539,6 +541,53 @@ void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
}
EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
+static void serial8250_rpm_get(struct uart_8250_port *p)
+{
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+ pm_runtime_get_sync(p->port.dev);
+}
+
+static void serial8250_rpm_put(struct uart_8250_port *p)
+{
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+ pm_runtime_mark_last_busy(p->port.dev);
+ pm_runtime_put_autosuspend(p->port.dev);
+}
+
+/*
+ * This two wrapper ensure, that enable_runtime_pm_tx() can be called more than
+ * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
+ * empty and the HW can idle again.
+ */
+static void serial8250_rpm_get_tx(struct uart_8250_port *p)
+{
+ unsigned char rpm_active;
+
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+
+ rpm_active = xchg(&p->rpm_tx_active, 1);
+ if (rpm_active)
+ return;
+ pm_runtime_get_sync(p->port.dev);
+}
+
+static void serial8250_rpm_put_tx(struct uart_8250_port *p)
+{
+ unsigned char rpm_active;
+
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+
+ rpm_active = xchg(&p->rpm_tx_active, 0);
+ if (!rpm_active)
+ return;
+ pm_runtime_mark_last_busy(p->port.dev);
+ pm_runtime_put_autosuspend(p->port.dev);
+}
+
/*
* IER sleep support. UARTs which have EFRs need the "extended
* capability" bit enabled. Note that on XR16C850s, we need to
@@ -553,10 +602,11 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
* offset but the UART channel may only write to the corresponding
* bit.
*/
+ serial8250_rpm_get(p);
if ((p->port.type == PORT_XR17V35X) ||
(p->port.type == PORT_XR17D15X)) {
serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
- return;
+ goto out;
}
if (p->capabilities & UART_CAP_SLEEP) {
@@ -572,6 +622,8 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
serial_out(p, UART_LCR, 0);
}
}
+out:
+ serial8250_rpm_put(p);
}
#ifdef CONFIG_SERIAL_8250_RSA
@@ -1272,6 +1324,7 @@ static inline void __stop_tx(struct uart_8250_port *p)
if (p->ier & UART_IER_THRI) {
p->ier &= ~UART_IER_THRI;
serial_out(p, UART_IER, p->ier);
+ serial8250_rpm_put_tx(p);
}
}
@@ -1279,6 +1332,7 @@ static void serial8250_stop_tx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
+ serial8250_rpm_get(up);
__stop_tx(up);
/*
@@ -1288,12 +1342,14 @@ static void serial8250_stop_tx(struct uart_port *port)
up->acr |= UART_ACR_TXDIS;
serial_icr_write(up, UART_ACR, up->acr);
}
+ serial8250_rpm_put(up);
}
static void serial8250_start_tx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
+ serial8250_rpm_get_tx(up);
if (up->dma && !serial8250_tx_dma(up)) {
return;
} else if (!(up->ier & UART_IER_THRI)) {
@@ -1318,13 +1374,27 @@ static void serial8250_start_tx(struct uart_port *port)
}
}
+static void serial8250_throttle(struct uart_port *port)
+{
+ port->throttle(port);
+}
+
+static void serial8250_unthrottle(struct uart_port *port)
+{
+ port->unthrottle(port);
+}
+
static void serial8250_stop_rx(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
- up->ier &= ~UART_IER_RLSI;
+ serial8250_rpm_get(up);
+
+ up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
up->port.read_status_mask &= ~UART_LSR_DR;
serial_port_out(port, UART_IER, up->ier);
+
+ serial8250_rpm_put(up);
}
static void serial8250_enable_ms(struct uart_port *port)
@@ -1336,7 +1406,10 @@ static void serial8250_enable_ms(struct uart_port *port)
return;
up->ier |= UART_IER_MSI;
+
+ serial8250_rpm_get(up);
serial_port_out(port, UART_IER, up->ier);
+ serial8250_rpm_put(up);
}
/*
@@ -1458,11 +1531,17 @@ void serial8250_tx_chars(struct uart_8250_port *up)
DEBUG_INTR("THRE...");
- if (uart_circ_empty(xmit))
+ /*
+ * With RPM enabled, we have to wait once the FIFO is empty before the
+ * HW can go idle. So we get here once again with empty FIFO and disable
+ * the interrupt and RPM in __stop_tx()
+ */
+ if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
__stop_tx(up);
}
EXPORT_SYMBOL_GPL(serial8250_tx_chars);
+/* Caller holds uart port lock */
unsigned int serial8250_modem_status(struct uart_8250_port *up)
{
struct uart_port *port = &up->port;
@@ -1525,9 +1604,17 @@ EXPORT_SYMBOL_GPL(serial8250_handle_irq);
static int serial8250_default_handle_irq(struct uart_port *port)
{
- unsigned int iir = serial_port_in(port, UART_IIR);
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned int iir;
+ int ret;
+
+ serial8250_rpm_get(up);
- return serial8250_handle_irq(port, iir);
+ iir = serial_port_in(port, UART_IIR);
+ ret = serial8250_handle_irq(port, iir);
+
+ serial8250_rpm_put(up);
+ return ret;
}
/*
@@ -1784,11 +1871,15 @@ static unsigned int serial8250_tx_empty(struct uart_port *port)
unsigned long flags;
unsigned int lsr;
+ serial8250_rpm_get(up);
+
spin_lock_irqsave(&port->lock, flags);
lsr = serial_port_in(port, UART_LSR);
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);
+
return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
}
@@ -1798,7 +1889,9 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port)
unsigned int status;
unsigned int ret;
+ serial8250_rpm_get(up);
status = serial8250_modem_status(up);
+ serial8250_rpm_put(up);
ret = 0;
if (status & UART_MSR_DCD)
@@ -1838,6 +1931,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
+ serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
@@ -1845,6 +1939,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state)
up->lcr &= ~UART_LCR_SBC;
serial_port_out(port, UART_LCR, up->lcr);
spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);
}
/*
@@ -1889,12 +1984,23 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits)
static int serial8250_get_poll_char(struct uart_port *port)
{
- unsigned char lsr = serial_port_in(port, UART_LSR);
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned char lsr;
+ int status;
+
+ serial8250_rpm_get(up);
+
+ lsr = serial_port_in(port, UART_LSR);
- if (!(lsr & UART_LSR_DR))
- return NO_POLL_CHAR;
+ if (!(lsr & UART_LSR_DR)) {
+ status = NO_POLL_CHAR;
+ goto out;
+ }
- return serial_port_in(port, UART_RX);
+ status = serial_port_in(port, UART_RX);
+out:
+ serial8250_rpm_put(up);
+ return status;
}
@@ -1904,6 +2010,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
unsigned int ier;
struct uart_8250_port *up = up_to_u8250p(port);
+ serial8250_rpm_get(up);
/*
* First save the IER then disable the interrupts
*/
@@ -1925,11 +2032,12 @@ static void serial8250_put_poll_char(struct uart_port *port,
*/
wait_for_xmitr(up, BOTH_EMPTY);
serial_port_out(port, UART_IER, ier);
+ serial8250_rpm_put(up);
}
#endif /* CONFIG_CONSOLE_POLL */
-static int serial8250_startup(struct uart_port *port)
+int serial8250_do_startup(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
@@ -1950,6 +2058,7 @@ static int serial8250_startup(struct uart_port *port)
if (port->iotype != up->cur_iotype)
set_io_from_upio(port);
+ serial8250_rpm_get(up);
if (port->type == PORT_16C950) {
/* Wake up and initialize UART */
up->acr = 0;
@@ -1970,7 +2079,6 @@ static int serial8250_startup(struct uart_port *port)
*/
enable_rsa(up);
#endif
-
/*
* Clear the FIFO buffers and disable them.
* (they will be reenabled in set_termios())
@@ -1980,8 +2088,8 @@ static int serial8250_startup(struct uart_port *port)
/*
* Clear the interrupt registers.
*/
- serial_port_in(port, UART_LSR);
- serial_port_in(port, UART_RX);
+ if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
+ serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
@@ -1994,7 +2102,8 @@ static int serial8250_startup(struct uart_port *port)
(serial_port_in(port, UART_LSR) == 0xff)) {
printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
serial_index(port));
- return -ENODEV;
+ retval = -ENODEV;
+ goto out;
}
/*
@@ -2079,7 +2188,7 @@ static int serial8250_startup(struct uart_port *port)
} else {
retval = serial_link_irq_chain(up);
if (retval)
- return retval;
+ goto out;
}
/*
@@ -2141,8 +2250,8 @@ dont_test_tx_en:
* saved flags to avoid getting false values from polling
* routines or the previous session.
*/
- serial_port_in(port, UART_LSR);
- serial_port_in(port, UART_RX);
+ if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
+ serial_port_in(port, UART_RX);
serial_port_in(port, UART_IIR);
serial_port_in(port, UART_MSR);
up->lsr_saved_flags = 0;
@@ -2177,15 +2286,26 @@ dont_test_tx_en:
outb_p(0x80, icp);
inb_p(icp);
}
+ retval = 0;
+out:
+ serial8250_rpm_put(up);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(serial8250_do_startup);
- return 0;
+static int serial8250_startup(struct uart_port *port)
+{
+ if (port->startup)
+ return port->startup(port);
+ return serial8250_do_startup(port);
}
-static void serial8250_shutdown(struct uart_port *port)
+void serial8250_do_shutdown(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
unsigned long flags;
+ serial8250_rpm_get(up);
/*
* Disable interrupts from this port
*/
@@ -2224,13 +2344,24 @@ static void serial8250_shutdown(struct uart_port *port)
* Read data port to reset things, and then unlink from
* the IRQ chain.
*/
- serial_port_in(port, UART_RX);
+ if (serial_port_in(port, UART_LSR) & UART_LSR_DR)
+ serial_port_in(port, UART_RX);
+ serial8250_rpm_put(up);
del_timer_sync(&up->timer);
up->timer.function = serial8250_timeout;
if (port->irq)
serial_unlink_irq_chain(up);
}
+EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
+
+static void serial8250_shutdown(struct uart_port *port)
+{
+ if (port->shutdown)
+ port->shutdown(port);
+ else
+ serial8250_do_shutdown(port);
+}
static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud)
{
@@ -2319,11 +2450,9 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
* the trigger, or the MCR RTS bit is cleared. In the case where
* the remote UART is not using CTS auto flow control, we must
* have sufficient FIFO entries for the latency of the remote
- * UART to respond. IOW, at least 32 bytes of FIFO. Also enable
- * AFE if hw flow control is supported
+ * UART to respond. IOW, at least 32 bytes of FIFO.
*/
- if ((up->capabilities & UART_CAP_AFE && (port->fifosize >= 32)) ||
- (port->flags & UPF_HARD_FLOW)) {
+ if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
up->mcr &= ~UART_MCR_AFE;
if (termios->c_cflag & CRTSCTS)
up->mcr |= UART_MCR_AFE;
@@ -2333,6 +2462,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
+ serial8250_rpm_get(up);
spin_lock_irqsave(&port->lock, flags);
/*
@@ -2454,6 +2584,8 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
}
serial8250_set_mctrl(port, port->mctrl);
spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);