Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic Fix race condition introduced in rev 1.189; after...



details:   https://anonhg.NetBSD.org/src/rev/d24c22ce0705
branches:  trunk
changeset: 565382:d24c22ce0705
user:      enami <enami%NetBSD.org@localhost>
date:      Mon Apr 05 22:33:08 2004 +0000

description:
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 6c19bd8cf6ce -r d24c22ce0705 sys/dev/ic/com.c
--- a/sys/dev/ic/com.c  Mon Apr 05 21:49:21 2004 +0000
+++ b/sys/dev/ic/com.c  Mon Apr 05 22:33:08 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: com.c,v 1.224 2004/01/23 05:01:19 simonb Exp $ */
+/*     $NetBSD: com.c,v 1.225 2004/04/05 22:33:08 enami Exp $  */
 
 /*-
  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -73,7 +73,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: com.c,v 1.224 2004/01/23 05:01:19 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: com.c,v 1.225 2004/04/05 22:33:08 enami Exp $");
 
 #include "opt_com.h"
 #include "opt_ddb.h"
@@ -2231,12 +2231,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