Skip to content

Commit 2c0ac5b

Browse files
jan-kiszkagregkh
authored andcommitted
serial: exar: Fix stuck MSIs
After migrating 8250_exar to MSI in 172c33c, we can get stuck without further interrupts because of the special wake-up event these chips send. They are only cleared by reading INT0. As we fail to do so during startup and shutdown, we can leave the interrupt line asserted, which is fatal with edge-triggered MSIs. Add the required reading of INT0 to startup and shutdown. Also account for the fact that a pending wake-up interrupt means we have to return 1 from exar_handle_irq. Drop the unneeded reading of INT1..3 along with this - those never reset anything. An alternative approach would have been disabling the wake-up interrupt. Unfortunately, this feature (REGB[17] = 1) is not available on the XR17D15X. Fixes: 172c33c ("serial: exar: Enable MSI support") Signed-off-by: Jan Kiszka <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Cc: stable <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent be40597 commit 2c0ac5b

File tree

1 file changed

+10
-9
lines changed

1 file changed

+10
-9
lines changed

drivers/tty/serial/8250/8250_port.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
/*
4848
* These are definitions for the Exar XR17V35X and XR17(C|D)15X
4949
*/
50+
#define UART_EXAR_INT0 0x80
5051
#define UART_EXAR_SLEEP 0x8b /* Sleep mode */
5152
#define UART_EXAR_DVID 0x8d /* Device identification */
5253

@@ -1869,17 +1870,13 @@ static int serial8250_default_handle_irq(struct uart_port *port)
18691870
static int exar_handle_irq(struct uart_port *port)
18701871
{
18711872
unsigned int iir = serial_port_in(port, UART_IIR);
1872-
int ret;
1873+
int ret = 0;
18731874

1874-
ret = serial8250_handle_irq(port, iir);
1875+
if (((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X)) &&
1876+
serial_port_in(port, UART_EXAR_INT0) != 0)
1877+
ret = 1;
18751878

1876-
if ((port->type == PORT_XR17V35X) ||
1877-
(port->type == PORT_XR17D15X)) {
1878-
serial_port_in(port, 0x80);
1879-
serial_port_in(port, 0x81);
1880-
serial_port_in(port, 0x82);
1881-
serial_port_in(port, 0x83);
1882-
}
1879+
ret |= serial8250_handle_irq(port, iir);
18831880

18841881
return ret;
18851882
}
@@ -2177,6 +2174,8 @@ int serial8250_do_startup(struct uart_port *port)
21772174
serial_port_in(port, UART_RX);
21782175
serial_port_in(port, UART_IIR);
21792176
serial_port_in(port, UART_MSR);
2177+
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
2178+
serial_port_in(port, UART_EXAR_INT0);
21802179

21812180
/*
21822181
* At this point, there's no way the LSR could still be 0xff;
@@ -2335,6 +2334,8 @@ int serial8250_do_startup(struct uart_port *port)
23352334
serial_port_in(port, UART_RX);
23362335
serial_port_in(port, UART_IIR);
23372336
serial_port_in(port, UART_MSR);
2337+
if ((port->type == PORT_XR17V35X) || (port->type == PORT_XR17D15X))
2338+
serial_port_in(port, UART_EXAR_INT0);
23382339
up->lsr_saved_flags = 0;
23392340
up->msr_saved_flags = 0;
23402341

0 commit comments

Comments
 (0)