summaryrefslogtreecommitdiffstats
path: root/sys/dev/uart/uart_dev_ns8250.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2009-04-08 00:14:06 +0000
committermarcel <marcel@FreeBSD.org>2009-04-08 00:14:06 +0000
commitd6a5c8810df83f81cd0e745553665359be0abfc1 (patch)
treee4d6f8709d7f3a10be086c4fd72f1db98ce562a4 /sys/dev/uart/uart_dev_ns8250.c
parent2444e34b785a96d6ce99f6cdbb9e60bb81ab4ebb (diff)
downloadFreeBSD-src-d6a5c8810df83f81cd0e745553665359be0abfc1.zip
FreeBSD-src-d6a5c8810df83f81cd0e745553665359be0abfc1.tar.gz
Fix hangs caused by hardware that signals receive errors
(framing, parity, etc), but does not indicate characters being received. Since no chracters have been received, ignore the line errors. PR: 131006 MFC after: 3 days
Diffstat (limited to 'sys/dev/uart/uart_dev_ns8250.c')
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 81642b2..c01fd61 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -50,14 +50,16 @@ __FBSDID("$FreeBSD$");
static void
ns8250_clrint(struct uart_bas *bas)
{
- uint8_t iir;
+ uint8_t iir, lsr;
iir = uart_getreg(bas, REG_IIR);
while ((iir & IIR_NOPEND) == 0) {
iir &= IIR_IMASK;
- if (iir == IIR_RLS)
- (void)uart_getreg(bas, REG_LSR);
- else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
+ if (iir == IIR_RLS) {
+ lsr = uart_getreg(bas, REG_LSR);
+ if (lsr & (LSR_BI|LSR_FE|LSR_PE))
+ (void)uart_getreg(bas, REG_DATA);
+ } else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
(void)uart_getreg(bas, REG_DATA);
else if (iir == IIR_MLSC)
(void)uart_getreg(bas, REG_MSR);
@@ -587,7 +589,6 @@ ns8250_bus_ipend(struct uart_softc *sc)
ipend = 0;
if (iir & IIR_RXRDY) {
lsr = uart_getreg(bas, REG_LSR);
- uart_unlock(sc->sc_hwmtx);
if (lsr & LSR_OE)
ipend |= SER_INT_OVERRUN;
if (lsr & LSR_BI)
@@ -595,12 +596,14 @@ ns8250_bus_ipend(struct uart_softc *sc)
if (lsr & LSR_RXRDY)
ipend |= SER_INT_RXREADY;
} else {
- uart_unlock(sc->sc_hwmtx);
if (iir & IIR_TXRDY)
ipend |= SER_INT_TXIDLE;
else
ipend |= SER_INT_SIGCHG;
}
+ if (ipend == 0)
+ ns8250_clrint(bas);
+ uart_unlock(sc->sc_hwmtx);
return ((sc->sc_leaving) ? 0 : ipend);
}
OpenPOWER on IntegriCloud