mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
TTY/Serial driver fixes for 6.9-rc5
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZiT5AA8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yli4QCeI7KNJxNI16CaI6tnVaKuhoWV8xkAn0Km6i4v 86MWyM8lo/GPpz18Jk13 =9vjg -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
c0c6b5c090
1
.mailmap
1
.mailmap
@ -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 Delgado <ribalda@kernel.org>
|
||||
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> <me@g0hl1n.net>
|
||||
Richard Leitner <richard.leitner@linux.dev> <richard.leitner@skidata.com>
|
||||
|
@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
title: Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART)
|
||||
|
||||
maintainers:
|
||||
- Richard Genoud <richard.genoud@gmail.com>
|
||||
- Richard Genoud <richard.genoud@bootlin.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -14356,7 +14356,7 @@ F: drivers/dma/at_xdmac.c
|
||||
F: include/dt-bindings/dma/at91.h
|
||||
|
||||
MICROCHIP AT91 SERIAL DRIVER
|
||||
M: Richard Genoud <richard.genoud@gmail.com>
|
||||
M: Richard Genoud <richard.genoud@bootlin.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
|
||||
F: drivers/tty/serial/atmel_serial.c
|
||||
|
@ -356,9 +356,9 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
||||
long rate;
|
||||
int ret;
|
||||
|
||||
clk_disable_unprepare(d->clk);
|
||||
rate = clk_round_rate(d->clk, newrate);
|
||||
if (rate > 0 && p->uartclk != rate) {
|
||||
clk_disable_unprepare(d->clk);
|
||||
if (rate > 0) {
|
||||
/*
|
||||
* Note that any clock-notifer worker will block in
|
||||
* serial8250_update_uartclk() until we are done.
|
||||
@ -366,8 +366,8 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
|
||||
ret = clk_set_rate(d->clk, newrate);
|
||||
if (!ret)
|
||||
p->uartclk = rate;
|
||||
clk_prepare_enable(d->clk);
|
||||
}
|
||||
clk_prepare_enable(d->clk);
|
||||
|
||||
dw8250_do_set_termios(p, termios, old);
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev)
|
||||
|
||||
ret = uart_read_port_properties(&uart.port);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto dis_uart_clk;
|
||||
|
||||
uart.port.iotype = UPIO_MEM32;
|
||||
uart.port.regshift = 2;
|
||||
|
@ -5010,12 +5010,6 @@ static const struct pci_device_id serial_pci_tbl[] = {
|
||||
{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B,
|
||||
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
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_ANY_ID, PCI_ANY_ID, 0, 0,
|
||||
pbn_b0_bt_4_460800 },
|
||||
|
@ -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)
|
||||
{
|
||||
u32 istat;
|
||||
u32 istat, stat;
|
||||
struct mxs_auart_port *s = context;
|
||||
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);
|
||||
|
||||
/* ack irq */
|
||||
@ -1126,6 +1128,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
|
||||
istat &= ~AUART_INTR_TXIS;
|
||||
}
|
||||
|
||||
uart_port_unlock(&s->port);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,6 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
|
||||
{
|
||||
struct tty_port *port;
|
||||
unsigned char ch, r1, drop, flag;
|
||||
int loops = 0;
|
||||
|
||||
/* Sanity check, make sure the old bug is no longer happening */
|
||||
if (uap->port.state == NULL) {
|
||||
@ -291,24 +290,11 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
|
||||
if (r1 & Rx_OVR)
|
||||
tty_insert_flip_char(port, 0, TTY_OVERRUN);
|
||||
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);
|
||||
if (!(ch & Rx_CH_AV))
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
flood:
|
||||
pmz_interrupt_control(uap, 0);
|
||||
pmz_error("pmz: rx irq flood !\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ struct serial_ctrl_device {
|
||||
struct serial_port_device {
|
||||
struct device dev;
|
||||
struct uart_port *port;
|
||||
unsigned int tx_enabled:1;
|
||||
};
|
||||
|
||||
int serial_base_ctrl_init(void);
|
||||
@ -30,6 +31,9 @@ void serial_base_ctrl_exit(void);
|
||||
int serial_base_port_init(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);
|
||||
void serial_base_driver_unregister(struct device_driver *driver);
|
||||
|
||||
|
@ -156,7 +156,7 @@ static void __uart_start(struct uart_state *state)
|
||||
* enabled, serial_port_runtime_resume() calls start_tx() again
|
||||
* 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);
|
||||
pm_runtime_mark_last_busy(&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,
|
||||
bool init_hw)
|
||||
{
|
||||
struct tty_port *port = &state->port;
|
||||
struct uart_port *uport;
|
||||
int retval;
|
||||
|
||||
if (tty_port_initialized(port))
|
||||
return 0;
|
||||
goto out_base_port_startup;
|
||||
|
||||
retval = uart_port_startup(tty, state, init_hw);
|
||||
if (retval)
|
||||
if (retval) {
|
||||
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)
|
||||
if (tty)
|
||||
set_bit(TTY_IO_ERROR, &tty->flags);
|
||||
|
||||
if (uport)
|
||||
serial_base_port_shutdown(uport);
|
||||
|
||||
if (tty_port_initialized(port)) {
|
||||
tty_port_set_initialized(port, false);
|
||||
|
||||
@ -1775,6 +1788,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
|
||||
uport->ops->stop_rx(uport);
|
||||
uart_port_unlock_irq(uport);
|
||||
|
||||
serial_base_port_shutdown(uport);
|
||||
uart_port_shutdown(port);
|
||||
|
||||
/*
|
||||
@ -1788,6 +1802,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
|
||||
* Free the transmit buffer.
|
||||
*/
|
||||
uart_port_lock_irq(uport);
|
||||
uart_circ_clear(&state->xmit);
|
||||
buf = state->xmit.buf;
|
||||
state->xmit.buf = NULL;
|
||||
uart_port_unlock_irq(uport);
|
||||
|
@ -39,8 +39,12 @@ static int serial_port_runtime_resume(struct device *dev)
|
||||
|
||||
/* Flush any pending TX for the port */
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
if (!port_dev->tx_enabled)
|
||||
goto unlock;
|
||||
if (__serial_port_busy(port))
|
||||
port->ops->start_tx(port);
|
||||
|
||||
unlock:
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
|
||||
out:
|
||||
@ -60,6 +64,11 @@ static int serial_port_runtime_suspend(struct device *dev)
|
||||
return 0;
|
||||
|
||||
uart_port_lock_irqsave(port, &flags);
|
||||
if (!port_dev->tx_enabled) {
|
||||
uart_port_unlock_irqrestore(port, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
busy = __serial_port_busy(port);
|
||||
if (busy)
|
||||
port->ops->start_tx(port);
|
||||
@ -71,6 +80,31 @@ static int serial_port_runtime_suspend(struct device *dev)
|
||||
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,
|
||||
serial_port_runtime_suspend,
|
||||
serial_port_runtime_resume, NULL);
|
||||
|
@ -861,6 +861,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
|
||||
u32 sr;
|
||||
unsigned int size;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
sr = readl_relaxed(port->membase + ofs->isr);
|
||||
|
||||
@ -869,11 +870,14 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
(sr & USART_SR_TC)) {
|
||||
stm32_usart_tc_interrupt_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,
|
||||
port->membase + ofs->icr);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) {
|
||||
/* Clear wake up flag and disable wake up interrupt */
|
||||
@ -882,6 +886,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
|
||||
if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
|
||||
pm_wakeup_event(tport->tty->dev, 0);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -896,6 +901,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
if (size)
|
||||
tty_flip_buffer_push(tport);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
@ -903,6 +909,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
uart_port_lock(port);
|
||||
stm32_usart_transmit_chars(port);
|
||||
uart_port_unlock(port);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* Receiver timeout irq for DMA RX */
|
||||
@ -912,9 +919,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
|
||||
uart_unlock_and_check_sysrq(port);
|
||||
if (size)
|
||||
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)
|
||||
@ -1084,6 +1092,7 @@ static int stm32_usart_startup(struct uart_port *port)
|
||||
val |= USART_CR2_SWAP;
|
||||
writel_relaxed(val, port->membase + ofs->cr2);
|
||||
}
|
||||
stm32_port->throttled = false;
|
||||
|
||||
/* RX FIFO Flush */
|
||||
if (ofs->rqr != UNDEF_REG)
|
||||
|
Loading…
Reference in New Issue
Block a user