summaryrefslogtreecommitdiff
path: root/drivers/tty
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/Kconfig4
-rw-r--r--drivers/tty/n_gsm.c2
-rw-r--r--drivers/tty/serial/8250/8250_early.c4
-rw-r--r--drivers/tty/serial/8250/8250_pci.c40
-rw-r--r--drivers/tty/serial/8250/8250_pcilib.c13
-rw-r--r--drivers/tty/serial/8250/8250_pcilib.h2
-rw-r--r--drivers/tty/serial/8250/8250_port.c29
-rw-r--r--drivers/tty/serial/8250/Kconfig4
-rw-r--r--drivers/tty/serial/Kconfig2
-rw-r--r--drivers/tty/serial/amba-pl010.c2
-rw-r--r--drivers/tty/serial/amba-pl011.c2
-rw-r--r--drivers/tty/serial/cpm_uart.c2
-rw-r--r--drivers/tty/serial/earlycon.c23
-rw-r--r--drivers/tty/serial/imx.c15
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c103
-rw-r--r--drivers/tty/serial/serial_core.c2
-rw-r--r--drivers/tty/serial/ucc_uart.c2
-rw-r--r--drivers/tty/sysrq.c18
-rw-r--r--drivers/tty/vt/vt.c2
19 files changed, 189 insertions, 82 deletions
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
index a45d423ad10f..63a494d36a1f 100644
--- a/drivers/tty/Kconfig
+++ b/drivers/tty/Kconfig
@@ -220,7 +220,7 @@ config MOXA_INTELLIO
config MOXA_SMARTIO
tristate "Moxa SmartIO support v. 2.0"
- depends on SERIAL_NONSTANDARD && PCI
+ depends on SERIAL_NONSTANDARD && PCI && HAS_IOPORT
help
Say Y here if you have a Moxa SmartIO multiport serial card and/or
want to help develop a new version of this driver.
@@ -302,7 +302,7 @@ config GOLDFISH_TTY_EARLY_CONSOLE
config IPWIRELESS
tristate "IPWireless 3G UMTS PCMCIA card support"
- depends on PCMCIA && NETDEVICES
+ depends on PCMCIA && NETDEVICES && HAS_IOPORT
select PPP
help
This is a driver for 3G UMTS PCMCIA card from IPWireless company. In
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 5d37a0984916..252849910588 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -3157,6 +3157,8 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
mutex_unlock(&gsm->mutex);
/* Now wipe the queues */
tty_ldisc_flush(gsm->tty);
+
+ guard(spinlock_irqsave)(&gsm->tx_lock);
list_for_each_entry_safe(txq, ntxq, &gsm->tx_ctrl_list, list)
kfree(txq);
INIT_LIST_HEAD(&gsm->tx_ctrl_list);
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index 6176083d0341..842422921765 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -46,8 +46,10 @@ static unsigned int serial8250_early_in(struct uart_port *port, int offset)
return readl(port->membase + offset);
case UPIO_MEM32BE:
return ioread32be(port->membase + offset);
+#ifdef CONFIG_HAS_IOPORT
case UPIO_PORT:
return inb(port->iobase + offset);
+#endif
default:
return 0;
}
@@ -70,9 +72,11 @@ static void serial8250_early_out(struct uart_port *port, int offset, int value)
case UPIO_MEM32BE:
iowrite32be(value, port->membase + offset);
break;
+#ifdef CONFIG_HAS_IOPORT
case UPIO_PORT:
outb(value, port->iobase + offset);
break;
+#endif
}
}
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 6709b6a5f301..7d7a6d62c09c 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -964,6 +964,9 @@ static int pci_ite887x_init(struct pci_dev *dev)
struct resource *iobase = NULL;
u32 miscr, uartbar, ioport;
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(dev);
+
/* search for the base-ioport */
for (i = 0; i < ARRAY_SIZE(inta_addr); i++) {
iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
@@ -1514,6 +1517,9 @@ static int pci_quatech_init(struct pci_dev *dev)
const struct pci_device_id *match;
bool amcc = false;
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(dev);
+
match = pci_match_id(quatech_cards, dev);
if (match)
amcc = match->driver_data;
@@ -1538,6 +1544,9 @@ static int pci_quatech_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(priv->dev);
+
/* Needed by pci_quatech calls below */
port->port.iobase = pci_resource_start(priv->dev, FL_GET_BASE(board->flags));
/* Set up the clocking */
@@ -1655,6 +1664,9 @@ static int pci_fintek_setup(struct serial_private *priv,
u8 config_base;
u16 iobase;
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(pdev);
+
config_base = 0x40 + 0x08 * idx;
/* Get the io address from configuration space */
@@ -1686,6 +1698,9 @@ static int pci_fintek_init(struct pci_dev *dev)
u8 config_base;
struct serial_private *priv = pci_get_drvdata(dev);
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(dev);
+
if (!(pci_resource_flags(dev, 5) & IORESOURCE_IO) ||
!(pci_resource_flags(dev, 4) & IORESOURCE_IO) ||
!(pci_resource_flags(dev, 3) & IORESOURCE_IO))
@@ -1864,6 +1879,9 @@ static int kt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(priv->dev);
+
port->port.flags |= UPF_BUG_THRE;
port->port.serial_in = kt_serial_in;
port->port.handle_break = kt_handle_break;
@@ -1884,6 +1902,9 @@ pci_wch_ch353_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(priv->dev);
+
port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16550A;
return pci_default_setup(priv, board, port, idx);
@@ -1894,6 +1915,9 @@ pci_wch_ch355_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(priv->dev);
+
port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16550A;
return pci_default_setup(priv, board, port, idx);
@@ -1904,6 +1928,9 @@ pci_wch_ch38x_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(priv->dev);
+
port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16850;
return pci_default_setup(priv, board, port, idx);
@@ -1918,6 +1945,8 @@ static int pci_wch_ch38x_init(struct pci_dev *dev)
int max_port;
unsigned long iobase;
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(dev);
switch (dev->device) {
case 0x3853: /* 8 ports */
@@ -1937,6 +1966,11 @@ static void pci_wch_ch38x_exit(struct pci_dev *dev)
{
unsigned long iobase;
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT)) {
+ serial_8250_warn_need_ioport(dev);
+ return;
+ }
+
iobase = pci_resource_start(dev, 0);
outb(0x0, iobase + CH384_XINT_ENABLE_REG);
}
@@ -2052,6 +2086,9 @@ static int pci_moxa_init(struct pci_dev *dev)
unsigned int i, num_ports = moxa_get_nports(device);
u8 val, init_mode = MOXA_RS232;
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(dev);
+
if (!(pci_moxa_supported_rs(dev) & MOXA_SUPP_RS232)) {
init_mode = MOXA_RS422;
}
@@ -2084,6 +2121,9 @@ pci_moxa_setup(struct serial_private *priv,
unsigned int bar = FL_GET_BASE(board->flags);
int offset;
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_warn_need_ioport(priv->dev);
+
if (board->num_ports == 4 && idx == 3)
offset = 7 * board->uart_offset;
else
diff --git a/drivers/tty/serial/8250/8250_pcilib.c b/drivers/tty/serial/8250/8250_pcilib.c
index ea906d721b2c..3bdccf76f71d 100644
--- a/drivers/tty/serial/8250/8250_pcilib.c
+++ b/drivers/tty/serial/8250/8250_pcilib.c
@@ -12,6 +12,15 @@
#include "8250.h"
#include "8250_pcilib.h"
+int serial_8250_warn_need_ioport(struct pci_dev *dev)
+{
+ dev_warn(&dev->dev,
+ "Serial port not supported because of missing I/O resource\n");
+
+ return -ENXIO;
+}
+EXPORT_SYMBOL_NS_GPL(serial_8250_warn_need_ioport, SERIAL_8250_PCI);
+
int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port,
u8 bar, unsigned int offset, int regshift)
{
@@ -27,12 +36,14 @@ int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port,
port->port.mapbase = pci_resource_start(dev, bar) + offset;
port->port.membase = pcim_iomap_table(dev)[bar] + offset;
port->port.regshift = regshift;
- } else {
+ } else if (IS_ENABLED(CONFIG_HAS_IOPORT)) {
port->port.iotype = UPIO_PORT;
port->port.iobase = pci_resource_start(dev, bar) + offset;
port->port.mapbase = 0;
port->port.membase = NULL;
port->port.regshift = 0;
+ } else {
+ return serial_8250_warn_need_ioport(dev);
}
return 0;
}
diff --git a/drivers/tty/serial/8250/8250_pcilib.h b/drivers/tty/serial/8250/8250_pcilib.h
index 1aaf1b50ce9c..16a274574cde 100644
--- a/drivers/tty/serial/8250/8250_pcilib.h
+++ b/drivers/tty/serial/8250/8250_pcilib.h
@@ -13,3 +13,5 @@ struct uart_8250_port;
int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port, u8 bar,
unsigned int offset, int regshift);
+
+int serial_8250_warn_need_ioport(struct pci_dev *dev);
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 3509af7dc52b..4d63d80e78a9 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -338,6 +338,7 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value)
serial_out(up, UART_DLM, value >> 8 & 0xff);
}
+#ifdef CONFIG_HAS_IOPORT
static unsigned int hub6_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
@@ -351,6 +352,7 @@ static void hub6_serial_out(struct uart_port *p, int offset, int value)
outb(p->hub6 - 1 + offset, p->iobase);
outb(value, p->iobase + 1);
}
+#endif /* CONFIG_HAS_IOPORT */
static unsigned int mem_serial_in(struct uart_port *p, int offset)
{
@@ -400,6 +402,7 @@ static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
return ioread32be(p->membase + offset);
}
+#ifdef CONFIG_HAS_IOPORT
static unsigned int io_serial_in(struct uart_port *p, int offset)
{
offset = offset << p->regshift;
@@ -411,6 +414,15 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
offset = offset << p->regshift;
outb(value, p->iobase + offset);
}
+#endif
+static unsigned int no_serial_in(struct uart_port *p, int offset)
+{
+ return (unsigned int)-1;
+}
+
+static void no_serial_out(struct uart_port *p, int offset, int value)
+{
+}
static int serial8250_default_handle_irq(struct uart_port *port);
@@ -422,10 +434,12 @@ static void set_io_from_upio(struct uart_port *p)
up->dl_write = default_serial_dl_write;
switch (p->iotype) {
+#ifdef CONFIG_HAS_IOPORT
case UPIO_HUB6:
p->serial_in = hub6_serial_in;
p->serial_out = hub6_serial_out;
break;
+#endif
case UPIO_MEM:
p->serial_in = mem_serial_in;
@@ -446,11 +460,16 @@ static void set_io_from_upio(struct uart_port *p)
p->serial_in = mem32be_serial_in;
p->serial_out = mem32be_serial_out;
break;
-
- default:
+#ifdef CONFIG_HAS_IOPORT
+ case UPIO_PORT:
p->serial_in = io_serial_in;
p->serial_out = io_serial_out;
break;
+#endif
+ default:
+ WARN(1, "Unsupported UART type %x\n", p->iotype);
+ p->serial_in = no_serial_in;
+ p->serial_out = no_serial_out;
}
/* Remember loaded iotype */
up->cur_iotype = p->iotype;
@@ -1174,7 +1193,7 @@ static void autoconfig(struct uart_8250_port *up)
*/
scratch = serial_in(up, UART_IER);
serial_out(up, UART_IER, 0);
-#ifdef __i386__
+#if defined(__i386__) && defined(CONFIG_HAS_IOPORT)
outb(0xff, 0x080);
#endif
/*
@@ -1183,7 +1202,7 @@ static void autoconfig(struct uart_8250_port *up)
*/
scratch2 = serial_in(up, UART_IER) & UART_IER_ALL_INTR;
serial_out(up, UART_IER, UART_IER_ALL_INTR);
-#ifdef __i386__
+#if defined(__i386__) && defined(CONFIG_HAS_IOPORT)
outb(0, 0x080);
#endif
scratch3 = serial_in(up, UART_IER) & UART_IER_ALL_INTR;
@@ -3176,7 +3195,7 @@ static void serial8250_config_port(struct uart_port *port, int flags)
static int
serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
{
- if (ser->irq >= nr_irqs || ser->irq < 0 ||
+ if (ser->irq >= irq_get_nr_irqs() || ser->irq < 0 ||
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
ser->type == PORT_STARTECH)
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 47ff50763c04..1eb20350fcf4 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -72,7 +72,7 @@ config SERIAL_8250_16550A_VARIANTS
config SERIAL_8250_FINTEK
bool "Support for Fintek variants"
- depends on SERIAL_8250
+ depends on SERIAL_8250 && HAS_IOPORT
help
Selecting this option will add support for the RS232 and RS485
capabilities of the Fintek F81216A LPC to 4 UART as well similar
@@ -163,7 +163,7 @@ config SERIAL_8250_HP300
config SERIAL_8250_CS
tristate "8250/16550 PCMCIA device support"
- depends on PCMCIA && SERIAL_8250
+ depends on PCMCIA && SERIAL_8250 && HAS_IOPORT
help
Say Y here to enable support for 16-bit PCMCIA serial devices,
including serial port cards, modems, and the modem functions of
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 28e4beeabf8f..45f0f779fbf9 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -877,7 +877,7 @@ config SERIAL_TXX9_STDSERIAL
config SERIAL_JSM
tristate "Digi International NEO and Classic PCI Support"
- depends on PCI
+ depends on PCI && HAS_IOPORT
select SERIAL_CORE
help
This is a driver for Digi International's Neo and Classic series
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index eabbf8afc9b5..c3a7fad02ac9 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -499,7 +499,7 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
int ret = 0;
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= nr_irqs)
+ if (ser->irq < 0 || ser->irq >= irq_get_nr_irqs())
ret = -EINVAL;
if (ser->baud_base < 9600)
ret = -EINVAL;
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 7d0134ecd82f..1c60850030b1 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2202,7 +2202,7 @@ static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser)
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= nr_irqs)
+ if (ser->irq < 0 || ser->irq >= irq_get_nr_irqs())
ret = -EINVAL;
if (ser->baud_base < 9600)
ret = -EINVAL;
diff --git a/drivers/tty/serial/cpm_uart.c b/drivers/tty/serial/cpm_uart.c
index a927478f581d..6eb8625de435 100644
--- a/drivers/tty/serial/cpm_uart.c
+++ b/drivers/tty/serial/cpm_uart.c
@@ -631,7 +631,7 @@ static int cpm_uart_verify_port(struct uart_port *port,
if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
ret = -EINVAL;
- if (ser->irq < 0 || ser->irq >= nr_irqs)
+ if (ser->irq < 0 || ser->irq >= irq_get_nr_irqs())
ret = -EINVAL;
if (ser->baud_base < 9600)
ret = -EINVAL;
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index a5fbb6ed38ae..ab9af37f6cda 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -248,6 +248,29 @@ static int __init param_setup_earlycon(char *buf)
}
early_param("earlycon", param_setup_earlycon);
+/*
+ * The `console` parameter is overloaded. It's handled here as an early param
+ * and in `printk.c` as a late param. It's possible to specify an early
+ * `bootconsole` using `earlycon=uartXXXX` (handled above), or via
+ * the `console=uartXXX` alias. See the comment in `8250_early.c`.
+ */
+static int __init param_setup_earlycon_console_alias(char *buf)
+{
+ /*
+ * A plain `console` parameter must not enable the SPCR `bootconsole`
+ * like a plain `earlycon` does.
+ *
+ * A `console=` parameter that specifies an empty value is used to
+ * disable the `console`, not the `earlycon` `bootconsole`. The
+ * disabling of the `console` is handled by `printk.c`.
+ */
+ if (!buf || !buf[0])
+ return 0;
+
+ return param_setup_earlycon(buf);
+}
+early_param("console", param_setup_earlycon_console_alias);
+
#ifdef CONFIG_OF_EARLY_FLATTREE
int __init of_setup_earlycon(const struct earlycon_id *match,
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 67d4a72eda77..90974d338f3c 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -762,6 +762,21 @@ static irqreturn_t __imx_uart_rtsint(int irq, void *dev_id)
imx_uart_writel(sport, USR1_RTSD, USR1);
usr1 = imx_uart_readl(sport, USR1) & USR1_RTSS;
+ /*
+ * Update sport->old_status here, so any follow-up calls to
+ * imx_uart_mctrl_check() will be able to recognize that RTS
+ * state changed since last imx_uart_mctrl_check() call.
+ *
+ * In case RTS has been detected as asserted here and later on
+ * deasserted by the time imx_uart_mctrl_check() was called,
+ * imx_uart_mctrl_check() can detect the RTS state change and
+ * trigger uart_handle_cts_change() to unblock the port for
+ * further TX transfers.
+ */
+ if (usr1 & USR1_RTSS)
+ sport->old_status |= TIOCM_CTS;
+ else
+ sport->old_status &= ~TIOCM_CTS;
uart_handle_cts_change(&sport->port, usr1);
wake_up_interruptible(&sport->port.state->port.delta_msr_wait);
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 6f0db310cf69..5dfe4e599ad6 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -147,6 +147,7 @@ static struct uart_driver qcom_geni_uart_driver;
static void __qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport);
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport);
+static int qcom_geni_serial_port_setup(struct uart_port *uport);
static inline struct qcom_geni_serial_port *to_dev_port(struct uart_port *uport)
{
@@ -395,6 +396,23 @@ static void qcom_geni_serial_poll_put_char(struct uart_port *uport,
writel(c, uport->membase + SE_GENI_TX_FIFOn);
qcom_geni_serial_poll_tx_done(uport);
}
+
+static int qcom_geni_serial_poll_init(struct uart_port *uport)
+{
+ struct qcom_geni_serial_port *port = to_dev_port(uport);
+ int ret;
+
+ if (!port->setup) {
+ ret = qcom_geni_serial_port_setup(uport);
+ if (ret)
+ return ret;
+ }
+
+ if (!qcom_geni_serial_secondary_active(uport))
+ geni_se_setup_s_cmd(&port->se, UART_START_READ, 0);
+
+ return 0;
+}
#endif
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
@@ -562,7 +580,7 @@ static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
}
#endif /* CONFIG_SERIAL_QCOM_GENI_CONSOLE */
-static void handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop)
+static void handle_rx_uart(struct uart_port *uport, u32 bytes)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
struct tty_port *tport = &uport->state->port;
@@ -570,9 +588,8 @@ static void handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop)
ret = tty_insert_flip_string(tport, port->rx_buf, bytes);
if (ret != bytes) {
- dev_err(uport->dev, "%s:Unable to push data ret %d_bytes %d\n",
- __func__, ret, bytes);
- WARN_ON_ONCE(1);
+ dev_err_ratelimited(uport->dev, "failed to push data (%d < %u)\n",
+ ret, bytes);
}
uport->icount.rx += ret;
tty_flip_buffer_push(tport);
@@ -787,17 +804,27 @@ static void qcom_geni_serial_start_rx_fifo(struct uart_port *uport)
static void qcom_geni_serial_stop_rx_dma(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
+ bool done;
if (!qcom_geni_serial_secondary_active(uport))
return;
geni_se_cancel_s_cmd(&port->se);
- qcom_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
- S_CMD_CANCEL_EN, true);
-
- if (qcom_geni_serial_secondary_active(uport))
+ done = qcom_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT,
+ RX_EOT, true);
+ if (done) {
+ writel(RX_EOT | RX_DMA_DONE,
+ uport->membase + SE_DMA_RX_IRQ_CLR);
+ } else {
qcom_geni_serial_abort_rx(uport);
+ writel(1, uport->membase + SE_DMA_RX_FSM_RST);
+ qcom_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT,
+ RX_RESET_DONE, true);
+ writel(RX_RESET_DONE | RX_DMA_DONE,
+ uport->membase + SE_DMA_RX_IRQ_CLR);
+ }
+
if (port->rx_dma_addr) {
geni_se_rx_dma_unprep(&port->se, port->rx_dma_addr,
DMA_RX_BUF_SIZE);
@@ -846,7 +873,7 @@ static void qcom_geni_serial_handle_rx_dma(struct uart_port *uport, bool drop)
}
if (!drop)
- handle_rx_uart(uport, rx_in, drop);
+ handle_rx_uart(uport, rx_in);
ret = geni_se_rx_dma_prep(&port->se, port->rx_buf,
DMA_RX_BUF_SIZE,
@@ -1096,10 +1123,12 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport)
{
disable_irq(uport->irq);
+ uart_port_lock_irq(uport);
qcom_geni_serial_stop_tx(uport);
qcom_geni_serial_stop_rx(uport);
qcom_geni_serial_cancel_tx_cmd(uport);
+ uart_port_unlock_irq(uport);
}
static void qcom_geni_serial_flush_buffer(struct uart_port *uport)
@@ -1152,7 +1181,6 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)
false, true, true);
geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2);
geni_se_select_mode(&port->se, port->dev_data->mode);
- qcom_geni_serial_start_rx(uport);
port->setup = true;
return 0;
@@ -1168,6 +1196,11 @@ static int qcom_geni_serial_startup(struct uart_port *uport)
if (ret)
return ret;
}
+
+ uart_port_lock_irq(uport);
+ qcom_geni_serial_start_rx(uport);
+ uart_port_unlock_irq(uport);
+
enable_irq(uport->irq);
return 0;
@@ -1253,7 +1286,6 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
unsigned int avg_bw_core;
unsigned long timeout;
- qcom_geni_serial_stop_rx(uport);
/* baud rate */
baud = uart_get_baud_rate(uport, termios, old, 300, 4000000);
@@ -1269,7 +1301,7 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
dev_err(port->se.dev,
"Couldn't find suitable clock rate for %u\n",
baud * sampling_rate);
- goto out_restart_rx;
+ return;
}
dev_dbg(port->se.dev, "desired_rate = %u, clk_rate = %lu, clk_div = %u\n",
@@ -1360,8 +1392,6 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN);
writel(ser_clk_cfg, uport->membase + GENI_SER_M_CLK_CFG);
writel(ser_clk_cfg, uport->membase + GENI_SER_S_CLK_CFG);
-out_restart_rx:
- qcom_geni_serial_start_rx(uport);
}
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
@@ -1582,7 +1612,7 @@ static const struct uart_ops qcom_geni_console_pops = {
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = qcom_geni_serial_get_char,
.poll_put_char = qcom_geni_serial_poll_put_char,
- .poll_init = qcom_geni_serial_port_setup,
+ .poll_init = qcom_geni_serial_poll_init,
#endif
.pm = qcom_geni_serial_pm,
};
@@ -1749,7 +1779,7 @@ static void qcom_geni_serial_remove(struct platform_device *pdev)
uart_remove_one_port(drv, &port->uport);
}
-static int qcom_geni_serial_sys_suspend(struct device *dev)
+static int qcom_geni_serial_suspend(struct device *dev)
{
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
struct uart_port *uport = &port->uport;
@@ -1766,7 +1796,7 @@ static int qcom_geni_serial_sys_suspend(struct device *dev)
return uart_suspend_port(private_data->drv, uport);
}
-static int qcom_geni_serial_sys_resume(struct device *dev)
+static int qcom_geni_serial_resume(struct device *dev)
{
int ret;
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
@@ -1781,38 +1811,6 @@ static int qcom_geni_serial_sys_resume(struct device *dev)
return ret;
}
-static int qcom_geni_serial_sys_hib_resume(struct device *dev)
-{
- int ret = 0;
- struct uart_port *uport;
- struct qcom_geni_private_data *private_data;
- struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
-
- uport = &port->uport;
- private_data = uport->private_data;
-
- if (uart_console(uport)) {
- geni_icc_set_tag(&port->se, QCOM_ICC_TAG_ALWAYS);
- geni_icc_set_bw(&port->se);
- ret = uart_resume_port(private_data->drv, uport);
- /*
- * For hibernation usecase clients for
- * console UART won't call port setup during restore,
- * hence call port setup for console uart.
- */
- qcom_geni_serial_port_setup(uport);
- } else {
- /*
- * Peripheral register settings are lost during hibernation.
- * Update setup flag such that port setup happens again
- * during next session. Clients of HS-UART will close and
- * open the port during hibernation.
- */
- port->setup = false;
- }
- return ret;
-}
-
static const struct qcom_geni_device_data qcom_geni_console_data = {
.console = true,
.mode = GENI_SE_FIFO,
@@ -1824,12 +1822,7 @@ static const struct qcom_geni_device_data qcom_geni_uart_data = {
};
static const struct dev_pm_ops qcom_geni_serial_pm_ops = {
- .suspend = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
- .resume = pm_sleep_ptr(qcom_geni_serial_sys_resume),
- .freeze = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
- .poweroff = pm_sleep_ptr(qcom_geni_serial_sys_suspend),
- .restore = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume),
- .thaw = pm_sleep_ptr(qcom_geni_serial_sys_hib_resume),
+ SYSTEM_SLEEP_PM_OPS(qcom_geni_serial_suspend, qcom_geni_serial_resume)
};
static const struct of_device_id qcom_geni_serial_match_table[] = {
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index d94d73e45fb6..74fa02b23772 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -919,7 +919,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
if (uport->ops->verify_port)
retval = uport->ops->verify_port(uport, new_info);
- if ((new_info->irq >= nr_irqs) || (new_info->irq < 0) ||
+ if ((new_info->irq >= irq_get_nr_irqs()) || (new_info->irq < 0) ||
(new_info->baud_base < 9600))
retval = -EINVAL;
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 53bb8c5ef499..4eed909468ff 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -1045,7 +1045,7 @@ static int qe_uart_verify_port(struct uart_port *port,
if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
return -EINVAL;
- if (ser->irq < 0 || ser->irq >= nr_irqs)
+ if (ser->irq < 0 || ser->irq >= irq_get_nr_irqs())
return -EINVAL;
if (ser->baud_base < 9600)
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 930b04e3d148..f85ce02e4725 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -583,7 +583,6 @@ static void __sysrq_put_key_op(u8 key, const struct sysrq_key_op *op_p)
void __handle_sysrq(u8 key, bool check_mask)
{
const struct sysrq_key_op *op_p;
- int orig_log_level;
int orig_suppress_printk;
int i;
@@ -593,13 +592,12 @@ void __handle_sysrq(u8 key, bool check_mask)
rcu_sysrq_start();
rcu_read_lock();
/*
- * Raise the apparent loglevel to maximum so that the sysrq header
- * is shown to provide the user with positive feedback. We do not
- * simply emit this at KERN_EMERG as that would change message
- * routing in the consumers of /proc/kmsg.
+ * Enter in the force_console context so that sysrq header is shown to
+ * provide the user with positive feedback. We do not simply emit this
+ * at KERN_EMERG as that would change message routing in the consumers
+ * of /proc/kmsg.
*/
- orig_log_level = console_loglevel;
- console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
+ printk_force_console_enter();
op_p = __sysrq_get_key_op(key);
if (op_p) {
@@ -609,11 +607,11 @@ void __handle_sysrq(u8 key, bool check_mask)
*/
if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
pr_info("%s\n", op_p->action_msg);
- console_loglevel = orig_log_level;
+ printk_force_console_exit();
op_p->handler(key);
} else {
pr_info("This sysrq operation is disabled.\n");
- console_loglevel = orig_log_level;
+ printk_force_console_exit();
}
} else {
pr_info("HELP : ");
@@ -631,7 +629,7 @@ void __handle_sysrq(u8 key, bool check_mask)
}
}
pr_cont("\n");
- console_loglevel = orig_log_level;
+ printk_force_console_exit();
}
rcu_read_unlock();
rcu_sysrq_end();
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index cd87e3d1291e..96842ce817af 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -4726,7 +4726,7 @@ static int con_font_get(struct vc_data *vc, struct console_font_op *op)
return -EINVAL;
if (op->data) {
- font.data = kvmalloc(max_font_size, GFP_KERNEL);
+ font.data = kvzalloc(max_font_size, GFP_KERNEL);
if (!font.data)
return -ENOMEM;
} else