summaryrefslogtreecommitdiffstats
path: root/sys/dev/uart/uart_core.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-09-17 03:11:32 +0000
committermarcel <marcel@FreeBSD.org>2003-09-17 03:11:32 +0000
commit920cfd2329dab9db239d8e448364bc546c00cc92 (patch)
tree4391e07d78aa2696fba66501852f450d6193838e /sys/dev/uart/uart_core.c
parentd07df62911128d99b66cd2768f1fbe4ae118b8a5 (diff)
downloadFreeBSD-src-920cfd2329dab9db239d8e448364bc546c00cc92.zip
FreeBSD-src-920cfd2329dab9db239d8e448364bc546c00cc92.tar.gz
In uart_intr() loop until all interrupts have been handled. Previously
an UART interface could get stuck when a new interrupt condition arose while servicing a previous interrupt. Since an interrupt was already pending, no new interrupt would be triggered. Avoid infinite recursion by flushing the Rx FIFO and marking an overrun condition when we could not move the data from the Rx FIFO to the receive buffer in toto. Failure to flush the Rx FIFO would leave the Rx ready condition pending. Note that the SAB 82532 already did this due to the nature of the chip.
Diffstat (limited to 'sys/dev/uart/uart_core.c')
-rw-r--r--sys/dev/uart/uart_core.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index dd4f91c..5889211 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -200,17 +200,21 @@ uart_intr(void *arg)
if (sc->sc_leaving)
return;
- ipend = UART_IPEND(sc);
- if (ipend & UART_IPEND_OVERRUN)
- uart_intr_overrun(sc);
- if (ipend & UART_IPEND_BREAK)
- uart_intr_break(sc);
- if (ipend & UART_IPEND_RXREADY)
- uart_intr_rxready(sc);
- if (ipend & UART_IPEND_SIGCHG)
- uart_intr_sigchg(sc);
- if (ipend & UART_IPEND_TXIDLE)
- uart_intr_txidle(sc);
+ do {
+ ipend = UART_IPEND(sc);
+ if (ipend == 0)
+ break;
+ if (ipend & UART_IPEND_OVERRUN)
+ uart_intr_overrun(sc);
+ if (ipend & UART_IPEND_BREAK)
+ uart_intr_break(sc);
+ if (ipend & UART_IPEND_RXREADY)
+ uart_intr_rxready(sc);
+ if (ipend & UART_IPEND_SIGCHG)
+ uart_intr_sigchg(sc);
+ if (ipend & UART_IPEND_TXIDLE)
+ uart_intr_txidle(sc);
+ } while (1);
if (sc->sc_opened && sc->sc_ttypend != 0)
swi_sched(sc->sc_softih, 0);
OpenPOWER on IntegriCloud