Author: marcel
Date: Wed Apr  8 00:14:06 2009
New Revision: 190834
URL: http://svn.freebsd.org/changeset/base/190834

Log:
  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

Modified:
  head/sys/dev/uart/uart_dev_ns8250.c

Modified: head/sys/dev/uart/uart_dev_ns8250.c
==============================================================================
--- head/sys/dev/uart/uart_dev_ns8250.c Tue Apr  7 22:26:53 2009        
(r190833)
+++ head/sys/dev/uart/uart_dev_ns8250.c Wed Apr  8 00:14:06 2009        
(r190834)
@@ -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);
 }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to