Commit c0c6b5c0 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull tty/serial driver fixes from Greg KH:
 "Here are some small tty and serial driver fixes for 6.9-rc5 that
  resolve a bunch of reported problems. Included in here are:

   - MAINTAINERS and .mailmap update for Richard Genoud

   - serial core regression fixes from 6.9-rc1 changes

   - pci id cleanups

   - serial core crash fix

   - stm32 driver fixes

   - 8250 driver fixes

  All of these have been in linux-next for a while with no reported
  problems"

* tag 'tty-6.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  serial: stm32: Reset .throttled state in .startup()
  serial: stm32: Return IRQ_NONE in the ISR if no handling happend
  serial: core: Fix missing shutdown and startup for serial base port
  serial: core: Clearing the circular buffer before NULLifying it
  MAINTAINERS: mailmap: update Richard Genoud's email address
  serial/pmac_zilog: Remove flawed mitigation for rx irq flood
  serial: 8250_pci: Remove redundant PCI IDs
  serial: core: Fix regression when runtime PM is not enabled
  serial: mxs-auart: add spinlock around changing cts state
  serial: 8250_dw: Revert: Do not reclock if already at correct rate
  serial: 8250_lpc18xx: disable clks on error in probe()
parents 5fa0ab45 ea2624b5
...@@ -525,6 +525,7 @@ Rémi Denis-Courmont <rdenis@simphalempin.com> ...@@ -525,6 +525,7 @@ Rémi Denis-Courmont <rdenis@simphalempin.com>
Ricardo Ribalda <ribalda@kernel.org> <ricardo@ribalda.com> Ricardo Ribalda <ribalda@kernel.org> <ricardo@ribalda.com>
Ricardo Ribalda <ribalda@kernel.org> Ricardo Ribalda Delgado <ribalda@kernel.org> Ricardo Ribalda <ribalda@kernel.org> Ricardo Ribalda Delgado <ribalda@kernel.org>
Ricardo Ribalda <ribalda@kernel.org> <ricardo.ribalda@gmail.com> Ricardo Ribalda <ribalda@kernel.org> <ricardo.ribalda@gmail.com>
Richard Genoud <richard.genoud@bootlin.com> <richard.genoud@gmail.com>
Richard Leitner <richard.leitner@linux.dev> <dev@g0hl1n.net> Richard Leitner <richard.leitner@linux.dev> <dev@g0hl1n.net>
Richard Leitner <richard.leitner@linux.dev> <me@g0hl1n.net> Richard Leitner <richard.leitner@linux.dev> <me@g0hl1n.net>
Richard Leitner <richard.leitner@linux.dev> <richard.leitner@skidata.com> Richard Leitner <richard.leitner@linux.dev> <richard.leitner@skidata.com>
......
...@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# ...@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) title: Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART)
maintainers: maintainers:
- Richard Genoud <richard.genoud@gmail.com> - Richard Genoud <richard.genoud@bootlin.com>
properties: properties:
compatible: compatible:
......
...@@ -14356,7 +14356,7 @@ F: drivers/dma/at_xdmac.c ...@@ -14356,7 +14356,7 @@ F: drivers/dma/at_xdmac.c
F: include/dt-bindings/dma/at91.h F: include/dt-bindings/dma/at91.h
MICROCHIP AT91 SERIAL DRIVER MICROCHIP AT91 SERIAL DRIVER
M: Richard Genoud <richard.genoud@gmail.com> M: Richard Genoud <richard.genoud@bootlin.com>
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml F: Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
F: drivers/tty/serial/atmel_serial.c F: drivers/tty/serial/atmel_serial.c
......
...@@ -356,9 +356,9 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, ...@@ -356,9 +356,9 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
long rate; long rate;
int ret; int ret;
clk_disable_unprepare(d->clk);
rate = clk_round_rate(d->clk, newrate); rate = clk_round_rate(d->clk, newrate);
if (rate > 0 && p->uartclk != rate) { if (rate > 0) {
clk_disable_unprepare(d->clk);
/* /*
* Note that any clock-notifer worker will block in * Note that any clock-notifer worker will block in
* serial8250_update_uartclk() until we are done. * serial8250_update_uartclk() until we are done.
...@@ -366,8 +366,8 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, ...@@ -366,8 +366,8 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
ret = clk_set_rate(d->clk, newrate); ret = clk_set_rate(d->clk, newrate);
if (!ret) if (!ret)
p->uartclk = rate; p->uartclk = rate;
clk_prepare_enable(d->clk);
} }
clk_prepare_enable(d->clk);
dw8250_do_set_termios(p, termios, old); dw8250_do_set_termios(p, termios, old);
} }
......
...@@ -151,7 +151,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) ...@@ -151,7 +151,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
ret = uart_read_port_properties(&uart.port); ret = uart_read_port_properties(&uart.port);
if (ret) if (ret)
return ret; goto dis_uart_clk;
uart.port.iotype = UPIO_MEM32; uart.port.iotype = UPIO_MEM32;
uart.port.regshift = 2; uart.port.regshift = 2;
......
...@@ -5010,12 +5010,6 @@ static const struct pci_device_id serial_pci_tbl[] = { ...@@ -5010,12 +5010,6 @@ static const struct pci_device_id serial_pci_tbl[] = {
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B, { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_2_115200 }, pbn_b0_bt_2_115200 },
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_A,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_2_115200 },
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_B,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_2_115200 },
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A, { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
pbn_b0_bt_4_460800 }, pbn_b0_bt_4_460800 },
......
...@@ -1086,11 +1086,13 @@ static void mxs_auart_set_ldisc(struct uart_port *port, ...@@ -1086,11 +1086,13 @@ static void mxs_auart_set_ldisc(struct uart_port *port,
static irqreturn_t mxs_auart_irq_handle(int irq, void *context) static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
{ {
u32 istat; u32 istat, stat;
struct mxs_auart_port *s = context; struct mxs_auart_port *s = context;
u32 mctrl_temp = s->mctrl_prev; u32 mctrl_temp = s->mctrl_prev;
u32 stat = mxs_read(s, REG_STAT);
uart_port_lock(&s->port);
stat = mxs_read(s, REG_STAT);
istat = mxs_read(s, REG_INTR); istat = mxs_read(s, REG_INTR);
/* ack irq */ /* ack irq */
...@@ -1126,6 +1128,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context) ...@@ -1126,6 +1128,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
istat &= ~AUART_INTR_TXIS; istat &= ~AUART_INTR_TXIS;
} }
uart_port_unlock(&s->port);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -210,7 +210,6 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap) ...@@ -210,7 +210,6 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
{ {
struct tty_port *port; struct tty_port *port;
unsigned char ch, r1, drop, flag; unsigned char ch, r1, drop, flag;
int loops = 0;
/* Sanity check, make sure the old bug is no longer happening */ /* Sanity check, make sure the old bug is no longer happening */
if (uap->port.state == NULL) { if (uap->port.state == NULL) {
...@@ -291,24 +290,11 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap) ...@@ -291,24 +290,11 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
if (r1 & Rx_OVR) if (r1 & Rx_OVR)
tty_insert_flip_char(port, 0, TTY_OVERRUN); tty_insert_flip_char(port, 0, TTY_OVERRUN);
next_char: next_char:
/* We can get stuck in an infinite loop getting char 0 when the
* line is in a wrong HW state, we break that here.
* When that happens, I disable the receive side of the driver.
* Note that what I've been experiencing is a real irq loop where
* I'm getting flooded regardless of the actual port speed.
* Something strange is going on with the HW
*/
if ((++loops) > 1000)
goto flood;
ch = read_zsreg(uap, R0); ch = read_zsreg(uap, R0);
if (!(ch & Rx_CH_AV)) if (!(ch & Rx_CH_AV))
break; break;
} }
return true;
flood:
pmz_interrupt_control(uap, 0);
pmz_error("pmz: rx irq flood !\n");
return true; return true;
} }
......
...@@ -22,6 +22,7 @@ struct serial_ctrl_device { ...@@ -22,6 +22,7 @@ struct serial_ctrl_device {
struct serial_port_device { struct serial_port_device {
struct device dev; struct device dev;
struct uart_port *port; struct uart_port *port;
unsigned int tx_enabled:1;
}; };
int serial_base_ctrl_init(void); int serial_base_ctrl_init(void);
...@@ -30,6 +31,9 @@ void serial_base_ctrl_exit(void); ...@@ -30,6 +31,9 @@ void serial_base_ctrl_exit(void);
int serial_base_port_init(void); int serial_base_port_init(void);
void serial_base_port_exit(void); void serial_base_port_exit(void);
void serial_base_port_startup(struct uart_port *port);
void serial_base_port_shutdown(struct uart_port *port);
int serial_base_driver_register(struct device_driver *driver); int serial_base_driver_register(struct device_driver *driver);
void serial_base_driver_unregister(struct device_driver *driver); void serial_base_driver_unregister(struct device_driver *driver);
......
...@@ -156,7 +156,7 @@ static void __uart_start(struct uart_state *state) ...@@ -156,7 +156,7 @@ static void __uart_start(struct uart_state *state)
* enabled, serial_port_runtime_resume() calls start_tx() again * enabled, serial_port_runtime_resume() calls start_tx() again
* after enabling the device. * after enabling the device.
*/ */
if (pm_runtime_active(&port_dev->dev)) if (!pm_runtime_enabled(port->dev) || pm_runtime_active(&port_dev->dev))
port->ops->start_tx(port); port->ops->start_tx(port);
pm_runtime_mark_last_busy(&port_dev->dev); pm_runtime_mark_last_busy(&port_dev->dev);
pm_runtime_put_autosuspend(&port_dev->dev); pm_runtime_put_autosuspend(&port_dev->dev);
...@@ -323,16 +323,26 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, ...@@ -323,16 +323,26 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state,
bool init_hw) bool init_hw)
{ {
struct tty_port *port = &state->port; struct tty_port *port = &state->port;
struct uart_port *uport;
int retval; int retval;
if (tty_port_initialized(port)) if (tty_port_initialized(port))
return 0; goto out_base_port_startup;
retval = uart_port_startup(tty, state, init_hw); retval = uart_port_startup(tty, state, init_hw);
if (retval) if (retval) {
set_bit(TTY_IO_ERROR, &tty->flags); set_bit(TTY_IO_ERROR, &tty->flags);
return retval;
}
return retval; out_base_port_startup:
uport = uart_port_check(state);
if (!uport)
return -EIO;
serial_base_port_startup(uport);
return 0;
} }
/* /*
...@@ -355,6 +365,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) ...@@ -355,6 +365,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
if (tty) if (tty)
set_bit(TTY_IO_ERROR, &tty->flags); set_bit(TTY_IO_ERROR, &tty->flags);
if (uport)
serial_base_port_shutdown(uport);
if (tty_port_initialized(port)) { if (tty_port_initialized(port)) {
tty_port_set_initialized(port, false); tty_port_set_initialized(port, false);
...@@ -1775,6 +1788,7 @@ static void uart_tty_port_shutdown(struct tty_port *port) ...@@ -1775,6 +1788,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
uport->ops->stop_rx(uport); uport->ops->stop_rx(uport);
uart_port_unlock_irq(uport); uart_port_unlock_irq(uport);
serial_base_port_shutdown(uport);
uart_port_shutdown(port); uart_port_shutdown(port);
/* /*
...@@ -1788,6 +1802,7 @@ static void uart_tty_port_shutdown(struct tty_port *port) ...@@ -1788,6 +1802,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
* Free the transmit buffer. * Free the transmit buffer.
*/ */
uart_port_lock_irq(uport); uart_port_lock_irq(uport);
uart_circ_clear(&state->xmit);
buf = state->xmit.buf; buf = state->xmit.buf;
state->xmit.buf = NULL; state->xmit.buf = NULL;
uart_port_unlock_irq(uport); uart_port_unlock_irq(uport);
......
...@@ -39,8 +39,12 @@ static int serial_port_runtime_resume(struct device *dev) ...@@ -39,8 +39,12 @@ static int serial_port_runtime_resume(struct device *dev)
/* Flush any pending TX for the port */ /* Flush any pending TX for the port */
uart_port_lock_irqsave(port, &flags); uart_port_lock_irqsave(port, &flags);
if (!port_dev->tx_enabled)
goto unlock;
if (__serial_port_busy(port)) if (__serial_port_busy(port))
port->ops->start_tx(port); port->ops->start_tx(port);
unlock:
uart_port_unlock_irqrestore(port, flags); uart_port_unlock_irqrestore(port, flags);
out: out:
...@@ -60,6 +64,11 @@ static int serial_port_runtime_suspend(struct device *dev) ...@@ -60,6 +64,11 @@ static int serial_port_runtime_suspend(struct device *dev)
return 0; return 0;
uart_port_lock_irqsave(port, &flags); uart_port_lock_irqsave(port, &flags);
if (!port_dev->tx_enabled) {
uart_port_unlock_irqrestore(port, flags);
return 0;
}
busy = __serial_port_busy(port); busy = __serial_port_busy(port);
if (busy) if (busy)
port->ops->start_tx(port); port->ops->start_tx(port);
...@@ -71,6 +80,31 @@ static int serial_port_runtime_suspend(struct device *dev) ...@@ -71,6 +80,31 @@ static int serial_port_runtime_suspend(struct device *dev)
return busy ? -EBUSY : 0; return busy ? -EBUSY : 0;
} }
static void serial_base_port_set_tx(struct uart_port *port,
struct serial_port_device *port_dev,
bool enabled)
{
unsigned long flags;
uart_port_lock_irqsave(port, &flags);
port_dev->tx_enabled = enabled;
uart_port_unlock_irqrestore(port, flags);
}
void serial_base_port_startup(struct uart_port *port)
{
struct serial_port_device *port_dev = port->port_dev;
serial_base_port_set_tx(port, port_dev, true);
}
void serial_base_port_shutdown(struct uart_port *port)
{
struct serial_port_device *port_dev = port->port_dev;
serial_base_port_set_tx(port, port_dev, false);
}
static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm, static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm,
serial_port_runtime_suspend, serial_port_runtime_suspend,
serial_port_runtime_resume, NULL); serial_port_runtime_resume, NULL);
......
...@@ -861,6 +861,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) ...@@ -861,6 +861,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
u32 sr; u32 sr;
unsigned int size; unsigned int size;
irqreturn_t ret = IRQ_NONE;
sr = readl_relaxed(port->membase + ofs->isr); sr = readl_relaxed(port->membase + ofs->isr);
...@@ -869,11 +870,14 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) ...@@ -869,11 +870,14 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
(sr & USART_SR_TC)) { (sr & USART_SR_TC)) {
stm32_usart_tc_interrupt_disable(port); stm32_usart_tc_interrupt_disable(port);
stm32_usart_rs485_rts_disable(port); stm32_usart_rs485_rts_disable(port);
ret = IRQ_HANDLED;
} }
if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) {
writel_relaxed(USART_ICR_RTOCF, writel_relaxed(USART_ICR_RTOCF,
port->membase + ofs->icr); port->membase + ofs->icr);
ret = IRQ_HANDLED;
}
if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) { if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) {
/* Clear wake up flag and disable wake up interrupt */ /* Clear wake up flag and disable wake up interrupt */
...@@ -882,6 +886,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) ...@@ -882,6 +886,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE); stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
if (irqd_is_wakeup_set(irq_get_irq_data(port->irq))) if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
pm_wakeup_event(tport->tty->dev, 0); pm_wakeup_event(tport->tty->dev, 0);
ret = IRQ_HANDLED;
} }
/* /*
...@@ -896,6 +901,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) ...@@ -896,6 +901,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
uart_unlock_and_check_sysrq(port); uart_unlock_and_check_sysrq(port);
if (size) if (size)
tty_flip_buffer_push(tport); tty_flip_buffer_push(tport);
ret = IRQ_HANDLED;
} }
} }
...@@ -903,6 +909,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) ...@@ -903,6 +909,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
uart_port_lock(port); uart_port_lock(port);
stm32_usart_transmit_chars(port); stm32_usart_transmit_chars(port);
uart_port_unlock(port); uart_port_unlock(port);
ret = IRQ_HANDLED;
} }
/* Receiver timeout irq for DMA RX */ /* Receiver timeout irq for DMA RX */
...@@ -912,9 +919,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) ...@@ -912,9 +919,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
uart_unlock_and_check_sysrq(port); uart_unlock_and_check_sysrq(port);
if (size) if (size)
tty_flip_buffer_push(tport); tty_flip_buffer_push(tport);
ret = IRQ_HANDLED;
} }
return IRQ_HANDLED; return ret;
} }
static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl) static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
...@@ -1084,6 +1092,7 @@ static int stm32_usart_startup(struct uart_port *port) ...@@ -1084,6 +1092,7 @@ static int stm32_usart_startup(struct uart_port *port)
val |= USART_CR2_SWAP; val |= USART_CR2_SWAP;
writel_relaxed(val, port->membase + ofs->cr2); writel_relaxed(val, port->membase + ofs->cr2);
} }
stm32_port->throttled = false;
/* RX FIFO Flush */ /* RX FIFO Flush */
if (ofs->rqr != UNDEF_REG) if (ofs->rqr != UNDEF_REG)
......
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