Commit 1cb67bcc authored by Linus Torvalds's avatar Linus Torvalds

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

Pull tty / serial fixes from Greg KH:
 "Here are some small serial driver fixes for 6.10-final. Included in
  here are:

   - qcom-geni fixes for a much much much discussed issue and everyone
     now seems to be agreed that this is the proper way forward to
     resolve the reported lockups

   - imx serial driver bugfixes

   - 8250_omap errata fix

   - ma35d1 serial driver bugfix

  All of these have been in linux-next for over a week with no reported
  issues"

* tag 'tty-6.10-final' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  serial: qcom-geni: do not kill the machine on fifo underrun
  serial: qcom-geni: fix hard lockup on buffer flush
  serial: qcom-geni: fix soft lockup on sw flow control and suspend
  serial: imx: ensure RTS signal is not left active after shutdown
  tty: serial: ma35d1: Add a NULL check for of_node
  serial: 8250_omap: Fix Errata i2310 with RX FIFO level check
  serial: imx: only set receiver level if it is zero
parents 1293147a 2ac33975
......@@ -672,7 +672,8 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id)
* https://www.ti.com/lit/pdf/sprz536
*/
if (priv->habit & UART_RX_TIMEOUT_QUIRK &&
(iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT) {
(iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT &&
serial_port_in(port, UART_OMAP_RX_LVL) == 0) {
unsigned char efr2, timeout_h, timeout_l;
efr2 = serial_in(up, UART_OMAP_EFR2);
......
......@@ -120,6 +120,7 @@
#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
#define UFCR_RXTL_MASK 0x3F /* Receiver trigger 6 bits wide */
#define UFCR_DCEDTE (1<<6) /* DCE/DTE mode select */
#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
#define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7)
......@@ -1551,6 +1552,7 @@ static void imx_uart_shutdown(struct uart_port *port)
struct imx_port *sport = (struct imx_port *)port;
unsigned long flags;
u32 ucr1, ucr2, ucr4, uts;
int loops;
if (sport->dma_is_enabled) {
dmaengine_terminate_sync(sport->dma_chan_tx);
......@@ -1613,6 +1615,56 @@ static void imx_uart_shutdown(struct uart_port *port)
ucr4 &= ~UCR4_TCEN;
imx_uart_writel(sport, ucr4, UCR4);
/*
* We have to ensure the tx state machine ends up in OFF. This
* is especially important for rs485 where we must not leave
* the RTS signal high, blocking the bus indefinitely.
*
* All interrupts are now disabled, so imx_uart_stop_tx() will
* no longer be called from imx_uart_transmit_buffer(). It may
* still be called via the hrtimers, and if those are in play,
* we have to honour the delays.
*/
if (sport->tx_state == WAIT_AFTER_RTS || sport->tx_state == SEND)
imx_uart_stop_tx(port);
/*
* In many cases (rs232 mode, or if tx_state was
* WAIT_AFTER_RTS, or if tx_state was SEND and there is no
* delay_rts_after_send), this will have moved directly to
* OFF. In rs485 mode, tx_state might already have been
* WAIT_AFTER_SEND and the hrtimer thus already started, or
* the above imx_uart_stop_tx() call could have started it. In
* those cases, we have to wait for the hrtimer to fire and
* complete the transition to OFF.
*/
loops = port->rs485.flags & SER_RS485_ENABLED ?
port->rs485.delay_rts_after_send : 0;
while (sport->tx_state != OFF && loops--) {
uart_port_unlock_irqrestore(&sport->port, flags);
msleep(1);
uart_port_lock_irqsave(&sport->port, &flags);
}
if (sport->tx_state != OFF) {
dev_warn(sport->port.dev, "unexpected tx_state %d\n",
sport->tx_state);
/*
* This machine may be busted, but ensure the RTS
* signal is inactive in order not to block other
* devices.
*/
if (port->rs485.flags & SER_RS485_ENABLED) {
ucr2 = imx_uart_readl(sport, UCR2);
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
imx_uart_rts_active(sport, &ucr2);
else
imx_uart_rts_inactive(sport, &ucr2);
imx_uart_writel(sport, ucr2, UCR2);
}
sport->tx_state = OFF;
}
uart_port_unlock_irqrestore(&sport->port, flags);
clk_disable_unprepare(sport->clk_per);
......@@ -1933,7 +1985,7 @@ static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termio
struct serial_rs485 *rs485conf)
{
struct imx_port *sport = (struct imx_port *)port;
u32 ucr2;
u32 ucr2, ufcr;
if (rs485conf->flags & SER_RS485_ENABLED) {
/* Enable receiver if low-active RTS signal is requested */
......@@ -1953,7 +2005,10 @@ static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termio
/* Make sure Rx is enabled in case Tx is active with Rx disabled */
if (!(rs485conf->flags & SER_RS485_ENABLED) ||
rs485conf->flags & SER_RS485_RX_DURING_TX) {
imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
/* If the receiver trigger is 0, set it to a default value */
ufcr = imx_uart_readl(sport, UFCR);
if ((ufcr & UFCR_RXTL_MASK) == 0)
imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
imx_uart_start_rx(port);
}
......
......@@ -688,12 +688,13 @@ static int ma35d1serial_probe(struct platform_device *pdev)
struct uart_ma35d1_port *up;
int ret = 0;
if (pdev->dev.of_node) {
ret = of_alias_get_id(pdev->dev.of_node, "serial");
if (ret < 0) {
dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", ret);
return ret;
}
if (!pdev->dev.of_node)
return -ENODEV;
ret = of_alias_get_id(pdev->dev.of_node, "serial");
if (ret < 0) {
dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", ret);
return ret;
}
up = &ma35d1serial_ports[ret];
up->port.line = ret;
......
......@@ -649,15 +649,25 @@ static void qcom_geni_serial_start_tx_dma(struct uart_port *uport)
static void qcom_geni_serial_start_tx_fifo(struct uart_port *uport)
{
unsigned char c;
u32 irq_en;
if (qcom_geni_serial_main_active(uport) ||
!qcom_geni_serial_tx_empty(uport))
return;
/*
* Start a new transfer in case the previous command was cancelled and
* left data in the FIFO which may prevent the watermark interrupt
* from triggering. Note that the stale data is discarded.
*/
if (!qcom_geni_serial_main_active(uport) &&
!qcom_geni_serial_tx_empty(uport)) {
if (uart_fifo_out(uport, &c, 1) == 1) {
writel(M_CMD_DONE_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
qcom_geni_serial_setup_tx(uport, 1);
writel(c, uport->membase + SE_GENI_TX_FIFOn);
}
}
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN;
writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
}
......@@ -665,13 +675,17 @@ static void qcom_geni_serial_start_tx_fifo(struct uart_port *uport)
static void qcom_geni_serial_stop_tx_fifo(struct uart_port *uport)
{
u32 irq_en;
struct qcom_geni_serial_port *port = to_dev_port(uport);
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
irq_en &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN);
writel(0, uport->membase + SE_GENI_TX_WATERMARK_REG);
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
/* Possible stop tx is called multiple times. */
}
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
if (!qcom_geni_serial_main_active(uport))
return;
......@@ -684,6 +698,8 @@ static void qcom_geni_serial_stop_tx_fifo(struct uart_port *uport)
writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
port->tx_remaining = 0;
}
static void qcom_geni_serial_handle_rx_fifo(struct uart_port *uport, bool drop)
......@@ -862,7 +878,7 @@ static void qcom_geni_serial_send_chunk_fifo(struct uart_port *uport,
memset(buf, 0, sizeof(buf));
tx_bytes = min(remaining, BYTES_PER_FIFO_WORD);
tx_bytes = uart_fifo_out(uport, buf, tx_bytes);
uart_fifo_out(uport, buf, tx_bytes);
iowrite32_rep(uport->membase + SE_GENI_TX_FIFOn, buf, 1);
......@@ -890,13 +906,17 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport,
else
pending = kfifo_len(&tport->xmit_fifo);
/* All data has been transmitted and acknowledged as received */
if (!pending && !status && done) {
/* All data has been transmitted or command has been cancelled */
if (!pending && done) {
qcom_geni_serial_stop_tx_fifo(uport);
goto out_write_wakeup;
}
avail = port->tx_fifo_depth - (status & TX_FIFO_WC);
if (active)
avail = port->tx_fifo_depth - (status & TX_FIFO_WC);
else
avail = port->tx_fifo_depth;
avail *= BYTES_PER_FIFO_WORD;
chunk = min(avail, pending);
......@@ -1069,11 +1089,15 @@ static void qcom_geni_serial_shutdown(struct uart_port *uport)
{
disable_irq(uport->irq);
if (uart_console(uport))
return;
qcom_geni_serial_stop_tx(uport);
qcom_geni_serial_stop_rx(uport);
qcom_geni_serial_cancel_tx_cmd(uport);
}
static void qcom_geni_serial_flush_buffer(struct uart_port *uport)
{
qcom_geni_serial_cancel_tx_cmd(uport);
}
static int qcom_geni_serial_port_setup(struct uart_port *uport)
......@@ -1532,6 +1556,7 @@ static const struct uart_ops qcom_geni_console_pops = {
.request_port = qcom_geni_serial_request_port,
.config_port = qcom_geni_serial_config_port,
.shutdown = qcom_geni_serial_shutdown,
.flush_buffer = qcom_geni_serial_flush_buffer,
.type = qcom_geni_serial_get_type,
.set_mctrl = qcom_geni_serial_set_mctrl,
.get_mctrl = qcom_geni_serial_get_mctrl,
......
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