Commit 52afe190 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'tty-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial fixes from Greg KH:
 "Here are some small tty and serial driver fixes for 5.1-rc3.

  Nothing major here, just a number of potential problems fixes for
  error handling paths, as well as some other minor bugfixes for
  reported issues with 5.1-rc1.

  All of these have been in linux-next with no reported issues"

* tag 'tty-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  tty: fix NULL pointer issue when tty_port ops is not set
  Disable kgdboc failed by echo space to /sys/module/kgdboc/parameters/kgdboc
  dt-bindings: serial: Add compatible for Mediatek MT8183
  tty/serial: atmel: RS485 HD w/DMA: enable RX after TX is stopped
  tty/serial: atmel: Add is_half_duplex helper
  serial: sh-sci: Fix setting SCSCR_TIE while transferring data
  serial: ar933x_uart: Fix build failure with disabled console
  tty: serial: qcom_geni_serial: Initialize baud in qcom_geni_console_setup
  sc16is7xx: missing unregister/delete driver on error in sc16is7xx_init()
  tty: mxs-auart: fix a potential NULL pointer dereference
  tty: atmel_serial: fix a potential NULL pointer dereference
  serial: max310x: Fix to avoid potential NULL pointer dereference
  serial: mvebu-uart: Fix to avoid a potential NULL pointer dereference
parents 8d02a9a8 f4e68d58
...@@ -16,6 +16,7 @@ Required properties: ...@@ -16,6 +16,7 @@ Required properties:
* "mediatek,mt8127-uart" for MT8127 compatible UARTS * "mediatek,mt8127-uart" for MT8127 compatible UARTS
* "mediatek,mt8135-uart" for MT8135 compatible UARTS * "mediatek,mt8135-uart" for MT8135 compatible UARTS
* "mediatek,mt8173-uart" for MT8173 compatible UARTS * "mediatek,mt8173-uart" for MT8173 compatible UARTS
* "mediatek,mt8183-uart", "mediatek,mt6577-uart" for MT8183 compatible UARTS
* "mediatek,mt6577-uart" for MT6577 and all of the above * "mediatek,mt6577-uart" for MT6577 and all of the above
- reg: The base address of the UART register bank. - reg: The base address of the UART register bank.
......
...@@ -49,11 +49,6 @@ struct ar933x_uart_port { ...@@ -49,11 +49,6 @@ struct ar933x_uart_port {
struct clk *clk; struct clk *clk;
}; };
static inline bool ar933x_uart_console_enabled(void)
{
return IS_ENABLED(CONFIG_SERIAL_AR933X_CONSOLE);
}
static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up, static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
int offset) int offset)
{ {
...@@ -508,6 +503,7 @@ static const struct uart_ops ar933x_uart_ops = { ...@@ -508,6 +503,7 @@ static const struct uart_ops ar933x_uart_ops = {
.verify_port = ar933x_uart_verify_port, .verify_port = ar933x_uart_verify_port,
}; };
#ifdef CONFIG_SERIAL_AR933X_CONSOLE
static struct ar933x_uart_port * static struct ar933x_uart_port *
ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS]; ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS];
...@@ -604,14 +600,7 @@ static struct console ar933x_uart_console = { ...@@ -604,14 +600,7 @@ static struct console ar933x_uart_console = {
.index = -1, .index = -1,
.data = &ar933x_uart_driver, .data = &ar933x_uart_driver,
}; };
#endif /* CONFIG_SERIAL_AR933X_CONSOLE */
static void ar933x_uart_add_console_port(struct ar933x_uart_port *up)
{
if (!ar933x_uart_console_enabled())
return;
ar933x_console_ports[up->port.line] = up;
}
static struct uart_driver ar933x_uart_driver = { static struct uart_driver ar933x_uart_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -700,7 +689,9 @@ static int ar933x_uart_probe(struct platform_device *pdev) ...@@ -700,7 +689,9 @@ static int ar933x_uart_probe(struct platform_device *pdev)
baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP); baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD); up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
ar933x_uart_add_console_port(up); #ifdef CONFIG_SERIAL_AR933X_CONSOLE
ar933x_console_ports[up->port.line] = up;
#endif
ret = uart_add_one_port(&ar933x_uart_driver, &up->port); ret = uart_add_one_port(&ar933x_uart_driver, &up->port);
if (ret) if (ret)
...@@ -749,8 +740,9 @@ static int __init ar933x_uart_init(void) ...@@ -749,8 +740,9 @@ static int __init ar933x_uart_init(void)
{ {
int ret; int ret;
if (ar933x_uart_console_enabled()) #ifdef CONFIG_SERIAL_AR933X_CONSOLE
ar933x_uart_driver.cons = &ar933x_uart_console; ar933x_uart_driver.cons = &ar933x_uart_console;
#endif
ret = uart_register_driver(&ar933x_uart_driver); ret = uart_register_driver(&ar933x_uart_driver);
if (ret) if (ret)
......
...@@ -166,6 +166,8 @@ struct atmel_uart_port { ...@@ -166,6 +166,8 @@ struct atmel_uart_port {
unsigned int pending_status; unsigned int pending_status;
spinlock_t lock_suspended; spinlock_t lock_suspended;
bool hd_start_rx; /* can start RX during half-duplex operation */
/* ISO7816 */ /* ISO7816 */
unsigned int fidi_min; unsigned int fidi_min;
unsigned int fidi_max; unsigned int fidi_max;
...@@ -231,6 +233,13 @@ static inline void atmel_uart_write_char(struct uart_port *port, u8 value) ...@@ -231,6 +233,13 @@ static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
__raw_writeb(value, port->membase + ATMEL_US_THR); __raw_writeb(value, port->membase + ATMEL_US_THR);
} }
static inline int atmel_uart_is_half_duplex(struct uart_port *port)
{
return ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) ||
(port->iso7816.flags & SER_ISO7816_ENABLED);
}
#ifdef CONFIG_SERIAL_ATMEL_PDC #ifdef CONFIG_SERIAL_ATMEL_PDC
static bool atmel_use_pdc_rx(struct uart_port *port) static bool atmel_use_pdc_rx(struct uart_port *port)
{ {
...@@ -608,10 +617,9 @@ static void atmel_stop_tx(struct uart_port *port) ...@@ -608,10 +617,9 @@ static void atmel_stop_tx(struct uart_port *port)
/* Disable interrupts */ /* Disable interrupts */
atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask); atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
if (((port->rs485.flags & SER_RS485_ENABLED) && if (atmel_uart_is_half_duplex(port))
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) ||
port->iso7816.flags & SER_ISO7816_ENABLED)
atmel_start_rx(port); atmel_start_rx(port);
} }
/* /*
...@@ -628,9 +636,7 @@ static void atmel_start_tx(struct uart_port *port) ...@@ -628,9 +636,7 @@ static void atmel_start_tx(struct uart_port *port)
return; return;
if (atmel_use_pdc_tx(port) || atmel_use_dma_tx(port)) if (atmel_use_pdc_tx(port) || atmel_use_dma_tx(port))
if (((port->rs485.flags & SER_RS485_ENABLED) && if (atmel_uart_is_half_duplex(port))
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) ||
port->iso7816.flags & SER_ISO7816_ENABLED)
atmel_stop_rx(port); atmel_stop_rx(port);
if (atmel_use_pdc_tx(port)) if (atmel_use_pdc_tx(port))
...@@ -928,11 +934,14 @@ static void atmel_complete_tx_dma(void *arg) ...@@ -928,11 +934,14 @@ static void atmel_complete_tx_dma(void *arg)
*/ */
if (!uart_circ_empty(xmit)) if (!uart_circ_empty(xmit))
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx); atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
else if (((port->rs485.flags & SER_RS485_ENABLED) && else if (atmel_uart_is_half_duplex(port)) {
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) || /*
port->iso7816.flags & SER_ISO7816_ENABLED) { * DMA done, re-enable TXEMPTY and signal that we can stop
/* DMA done, stop TX, start RX for RS485 */ * TX and start RX for RS485
atmel_start_rx(port); */
atmel_port->hd_start_rx = true;
atmel_uart_writel(port, ATMEL_US_IER,
atmel_port->tx_done_mask);
} }
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
...@@ -1288,6 +1297,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port) ...@@ -1288,6 +1297,10 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
sg_dma_len(&atmel_port->sg_rx)/2, sg_dma_len(&atmel_port->sg_rx)/2,
DMA_DEV_TO_MEM, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT); DMA_PREP_INTERRUPT);
if (!desc) {
dev_err(port->dev, "Preparing DMA cyclic failed\n");
goto chan_err;
}
desc->callback = atmel_complete_rx_dma; desc->callback = atmel_complete_rx_dma;
desc->callback_param = port; desc->callback_param = port;
atmel_port->desc_rx = desc; atmel_port->desc_rx = desc;
...@@ -1376,9 +1389,20 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending) ...@@ -1376,9 +1389,20 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending)
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (pending & atmel_port->tx_done_mask) { if (pending & atmel_port->tx_done_mask) {
/* Either PDC or interrupt transmission */
atmel_uart_writel(port, ATMEL_US_IDR, atmel_uart_writel(port, ATMEL_US_IDR,
atmel_port->tx_done_mask); atmel_port->tx_done_mask);
/* Start RX if flag was set and FIFO is empty */
if (atmel_port->hd_start_rx) {
if (!(atmel_uart_readl(port, ATMEL_US_CSR)
& ATMEL_US_TXEMPTY))
dev_warn(port->dev, "Should start RX, but TX fifo is not empty\n");
atmel_port->hd_start_rx = false;
atmel_start_rx(port);
return;
}
atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx); atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);
} }
} }
...@@ -1508,9 +1532,7 @@ static void atmel_tx_pdc(struct uart_port *port) ...@@ -1508,9 +1532,7 @@ static void atmel_tx_pdc(struct uart_port *port)
atmel_uart_writel(port, ATMEL_US_IER, atmel_uart_writel(port, ATMEL_US_IER,
atmel_port->tx_done_mask); atmel_port->tx_done_mask);
} else { } else {
if (((port->rs485.flags & SER_RS485_ENABLED) && if (atmel_uart_is_half_duplex(port)) {
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) ||
port->iso7816.flags & SER_ISO7816_ENABLED) {
/* DMA done, stop TX, start RX for RS485 */ /* DMA done, stop TX, start RX for RS485 */
atmel_start_rx(port); atmel_start_rx(port);
} }
......
...@@ -148,8 +148,10 @@ static int configure_kgdboc(void) ...@@ -148,8 +148,10 @@ static int configure_kgdboc(void)
char *cptr = config; char *cptr = config;
struct console *cons; struct console *cons;
if (!strlen(config) || isspace(config[0])) if (!strlen(config) || isspace(config[0])) {
err = 0;
goto noconfig; goto noconfig;
}
kgdboc_io_ops.is_console = 0; kgdboc_io_ops.is_console = 0;
kgdb_tty_driver = NULL; kgdb_tty_driver = NULL;
......
...@@ -1415,6 +1415,8 @@ static int max310x_spi_probe(struct spi_device *spi) ...@@ -1415,6 +1415,8 @@ static int max310x_spi_probe(struct spi_device *spi)
if (spi->dev.of_node) { if (spi->dev.of_node) {
const struct of_device_id *of_id = const struct of_device_id *of_id =
of_match_device(max310x_dt_ids, &spi->dev); of_match_device(max310x_dt_ids, &spi->dev);
if (!of_id)
return -ENODEV;
devtype = (struct max310x_devtype *)of_id->data; devtype = (struct max310x_devtype *)of_id->data;
} else { } else {
......
...@@ -810,6 +810,9 @@ static int mvebu_uart_probe(struct platform_device *pdev) ...@@ -810,6 +810,9 @@ static int mvebu_uart_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
if (!match)
return -ENODEV;
/* Assume that all UART ports have a DT alias or none has */ /* Assume that all UART ports have a DT alias or none has */
id = of_alias_get_id(pdev->dev.of_node, "serial"); id = of_alias_get_id(pdev->dev.of_node, "serial");
if (!pdev->dev.of_node || id < 0) if (!pdev->dev.of_node || id < 0)
......
...@@ -1686,6 +1686,10 @@ static int mxs_auart_probe(struct platform_device *pdev) ...@@ -1686,6 +1686,10 @@ static int mxs_auart_probe(struct platform_device *pdev)
s->port.mapbase = r->start; s->port.mapbase = r->start;
s->port.membase = ioremap(r->start, resource_size(r)); s->port.membase = ioremap(r->start, resource_size(r));
if (!s->port.membase) {
ret = -ENOMEM;
goto out_disable_clks;
}
s->port.ops = &mxs_auart_ops; s->port.ops = &mxs_auart_ops;
s->port.iotype = UPIO_MEM; s->port.iotype = UPIO_MEM;
s->port.fifosize = MXS_AUART_FIFO_SIZE; s->port.fifosize = MXS_AUART_FIFO_SIZE;
......
...@@ -1050,7 +1050,7 @@ static int __init qcom_geni_console_setup(struct console *co, char *options) ...@@ -1050,7 +1050,7 @@ static int __init qcom_geni_console_setup(struct console *co, char *options)
{ {
struct uart_port *uport; struct uart_port *uport;
struct qcom_geni_serial_port *port; struct qcom_geni_serial_port *port;
int baud; int baud = 9600;
int bits = 8; int bits = 8;
int parity = 'n'; int parity = 'n';
int flow = 'n'; int flow = 'n';
......
...@@ -1507,7 +1507,7 @@ static int __init sc16is7xx_init(void) ...@@ -1507,7 +1507,7 @@ static int __init sc16is7xx_init(void)
ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver); ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver);
if (ret < 0) { if (ret < 0) {
pr_err("failed to init sc16is7xx i2c --> %d\n", ret); pr_err("failed to init sc16is7xx i2c --> %d\n", ret);
return ret; goto err_i2c;
} }
#endif #endif
...@@ -1515,10 +1515,18 @@ static int __init sc16is7xx_init(void) ...@@ -1515,10 +1515,18 @@ static int __init sc16is7xx_init(void)
ret = spi_register_driver(&sc16is7xx_spi_uart_driver); ret = spi_register_driver(&sc16is7xx_spi_uart_driver);
if (ret < 0) { if (ret < 0) {
pr_err("failed to init sc16is7xx spi --> %d\n", ret); pr_err("failed to init sc16is7xx spi --> %d\n", ret);
return ret; goto err_spi;
} }
#endif #endif
return ret; return ret;
err_spi:
#ifdef CONFIG_SERIAL_SC16IS7XX_I2C
i2c_del_driver(&sc16is7xx_i2c_uart_driver);
#endif
err_i2c:
uart_unregister_driver(&sc16is7xx_uart);
return ret;
} }
module_init(sc16is7xx_init); module_init(sc16is7xx_init);
......
...@@ -838,19 +838,9 @@ static void sci_transmit_chars(struct uart_port *port) ...@@ -838,19 +838,9 @@ static void sci_transmit_chars(struct uart_port *port)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) { if (uart_circ_empty(xmit))
sci_stop_tx(port); sci_stop_tx(port);
} else {
ctrl = serial_port_in(port, SCSCR);
if (port->type != PORT_SCI) {
serial_port_in(port, SCxSR); /* Dummy read */
sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port));
}
ctrl |= SCSCR_TIE;
serial_port_out(port, SCSCR, ctrl);
}
} }
/* On SH3, SCIF may read end-of-break as a space->mark char */ /* On SH3, SCIF may read end-of-break as a space->mark char */
......
...@@ -325,7 +325,7 @@ static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty) ...@@ -325,7 +325,7 @@ static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
if (tty && C_HUPCL(tty)) if (tty && C_HUPCL(tty))
tty_port_lower_dtr_rts(port); tty_port_lower_dtr_rts(port);
if (port->ops->shutdown) if (port->ops && port->ops->shutdown)
port->ops->shutdown(port); port->ops->shutdown(port);
} }
out: out:
...@@ -398,7 +398,7 @@ EXPORT_SYMBOL_GPL(tty_port_tty_wakeup); ...@@ -398,7 +398,7 @@ EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
*/ */
int tty_port_carrier_raised(struct tty_port *port) int tty_port_carrier_raised(struct tty_port *port)
{ {
if (port->ops->carrier_raised == NULL) if (!port->ops || !port->ops->carrier_raised)
return 1; return 1;
return port->ops->carrier_raised(port); return port->ops->carrier_raised(port);
} }
...@@ -414,7 +414,7 @@ EXPORT_SYMBOL(tty_port_carrier_raised); ...@@ -414,7 +414,7 @@ EXPORT_SYMBOL(tty_port_carrier_raised);
*/ */
void tty_port_raise_dtr_rts(struct tty_port *port) void tty_port_raise_dtr_rts(struct tty_port *port)
{ {
if (port->ops->dtr_rts) if (port->ops && port->ops->dtr_rts)
port->ops->dtr_rts(port, 1); port->ops->dtr_rts(port, 1);
} }
EXPORT_SYMBOL(tty_port_raise_dtr_rts); EXPORT_SYMBOL(tty_port_raise_dtr_rts);
...@@ -429,7 +429,7 @@ EXPORT_SYMBOL(tty_port_raise_dtr_rts); ...@@ -429,7 +429,7 @@ EXPORT_SYMBOL(tty_port_raise_dtr_rts);
*/ */
void tty_port_lower_dtr_rts(struct tty_port *port) void tty_port_lower_dtr_rts(struct tty_port *port)
{ {
if (port->ops->dtr_rts) if (port->ops && port->ops->dtr_rts)
port->ops->dtr_rts(port, 0); port->ops->dtr_rts(port, 0);
} }
EXPORT_SYMBOL(tty_port_lower_dtr_rts); EXPORT_SYMBOL(tty_port_lower_dtr_rts);
...@@ -684,7 +684,7 @@ int tty_port_open(struct tty_port *port, struct tty_struct *tty, ...@@ -684,7 +684,7 @@ int tty_port_open(struct tty_port *port, struct tty_struct *tty,
if (!tty_port_initialized(port)) { if (!tty_port_initialized(port)) {
clear_bit(TTY_IO_ERROR, &tty->flags); clear_bit(TTY_IO_ERROR, &tty->flags);
if (port->ops->activate) { if (port->ops && port->ops->activate) {
int retval = port->ops->activate(port, tty); int retval = port->ops->activate(port, tty);
if (retval) { if (retval) {
mutex_unlock(&port->mutex); mutex_unlock(&port->mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment