Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-6]: src/sys/dev/ic Pull up revision 1.225 (requested by enami i...



details:   https://anonhg.NetBSD.org/src/rev/2c23a387ed13
branches:  netbsd-1-6
changeset: 531242:2c23a387ed13
user:      tron <tron%NetBSD.org@localhost>
date:      Tue Apr 06 07:59:18 2004 +0000

description:
Pull up revision 1.225 (requested by enami in ticket #1658):
Fix race condition introduced in rev 1.189; after the change, if there is
THRE interrupt occurs between the LSR read and IIR read, we won't see the
LSR_TXRDY bit when testing it in the variable `lsr' and we don't interrupted
again (as the corresponding bit in the IIR is cleared by reading, except
for some broken device).
Tested by Matthias Scheler and me, reviewed by Allen Briggs.
Closes PR#25010.

diffstat:

 sys/dev/ic/com.c |  24 ++++++++++++++++++------
 1 files changed, 18 insertions(+), 6 deletions(-)

diffs (47 lines):

diff -r 7507a5416298 -r 2c23a387ed13 sys/dev/ic/com.c
--- a/sys/dev/ic/com.c  Tue Apr 06 05:45:45 2004 +0000
+++ b/sys/dev/ic/com.c  Tue Apr 06 07:59:18 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: com.c,v 1.196 2002/04/13 17:05:16 christos Exp $       */
+/*     $NetBSD: com.c,v 1.196.4.1 2004/04/06 07:59:18 tron Exp $       */
 
 /*-
  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -77,7 +77,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: com.c,v 1.196 2002/04/13 17:05:16 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: com.c,v 1.196.4.1 2004/04/06 07:59:18 tron Exp $");
 
 #include "opt_com.h"
 #include "opt_ddb.h"
@@ -2196,12 +2196,24 @@
 
                        sc->sc_st_check = 1;
                }
-       } while (ISSET((iir = bus_space_read_1(iot, ioh, com_iir)), IIR_RXRDY)
-           || ((iir & IIR_IMASK) == 0));
+       } while (!ISSET((iir =
+           bus_space_read_1(iot, ioh, com_iir)), IIR_NOPEND) &&
+           /*
+            * Since some device (e.g., ST16C1550) doesn't clear IIR_TXRDY
+            * by IIR read, so we can't do this way: `process all interrupts,
+            * then do TX if possble'.
+            */
+           (iir & IIR_IMASK) != IIR_TXRDY);
 
        /*
-        * Done handling any receive interrupts. See if data can be
-        * transmitted as well. Schedule tx done event if no data left
+        * Read LSR again, since there may be an interrupt between
+        * the last LSR read and IIR read above.
+        */
+       lsr = bus_space_read_1(iot, ioh, com_lsr);
+
+       /*
+        * See if data can be transmitted as well.
+        * Schedule tx done event if no data left
         * and tty was marked busy.
         */
        if (ISSET(lsr, LSR_TXRDY)) {



Home | Main Index | Thread Index | Old Index