Skip to content

Commit 623b07b

Browse files
Jamm02gregkh
authored andcommitted
serial: 8250: 8250_omap.c: Add support for handling UART error conditions
The DMA IRQ handler does not accounts for the overrun(OE) or any other errors being reported by the IP before triggering a DMA transaction which leads to the interrupts not being handled resulting into an IRQ storm. The way to handle OE is to: 1. Reset the RX FIFO. 2. Read the UART_RESUME register, which clears the internal flag Earlier, the driver issued DMA transations even in case of OE which shouldn't be done according to the OE handling mechanism mentioned above, as we are resetting the FIFO's, refer section: "12.1.6.4.8.1.3.6 Overrun During Receive" [0]. [0] https://www.ti.com/lit/pdf/spruiu1 Signed-off-by: Moteen Shah <m-shah@ti.com> Link: https://patch.msgid.link/20260112081829.63049-2-m-shah@ti.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 93bb95a commit 623b07b

1 file changed

Lines changed: 21 additions & 2 deletions

File tree

drivers/tty/serial/8250/8250_omap.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@
100100
#define OMAP_UART_REV_52 0x0502
101101
#define OMAP_UART_REV_63 0x0603
102102

103+
/* Resume register */
104+
#define UART_OMAP_RESUME 0x0B
105+
103106
/* Interrupt Enable Register 2 */
104107
#define UART_OMAP_IER2 0x1B
105108
#define UART_OMAP_IER2_RHR_IT_DIS BIT(2)
@@ -119,7 +122,6 @@
119122
/* Timeout low and High */
120123
#define UART_OMAP_TO_L 0x26
121124
#define UART_OMAP_TO_H 0x27
122-
123125
struct omap8250_priv {
124126
void __iomem *membase;
125127
int line;
@@ -1256,6 +1258,20 @@ static u16 omap_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, u16 status
12561258
return status;
12571259
}
12581260

1261+
static void am654_8250_handle_uart_errors(struct uart_8250_port *up, u8 iir, u16 status)
1262+
{
1263+
if (status & UART_LSR_OE) {
1264+
serial8250_clear_and_reinit_fifos(up);
1265+
serial_in(up, UART_LSR);
1266+
serial_in(up, UART_OMAP_RESUME);
1267+
} else {
1268+
if (status & (UART_LSR_FE | UART_LSR_PE | UART_LSR_BI))
1269+
serial_in(up, UART_RX);
1270+
if (iir & UART_IIR_XOFF)
1271+
serial_in(up, UART_IIR);
1272+
}
1273+
}
1274+
12591275
static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
12601276
u16 status)
12611277
{
@@ -1266,7 +1282,8 @@ static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
12661282
* Queue a new transfer if FIFO has data.
12671283
*/
12681284
if ((status & (UART_LSR_DR | UART_LSR_BI)) &&
1269-
(up->ier & UART_IER_RDI)) {
1285+
(up->ier & UART_IER_RDI) && !(status & UART_LSR_OE)) {
1286+
am654_8250_handle_uart_errors(up, iir, status);
12701287
omap_8250_rx_dma(up);
12711288
serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE);
12721289
} else if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) {
@@ -1282,6 +1299,8 @@ static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
12821299
serial_out(up, UART_OMAP_EFR2, 0x0);
12831300
up->ier |= UART_IER_RLSI | UART_IER_RDI;
12841301
serial_out(up, UART_IER, up->ier);
1302+
} else {
1303+
am654_8250_handle_uart_errors(up, iir, status);
12851304
}
12861305
}
12871306

0 commit comments

Comments
 (0)