Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 03 Nov 2000 14:18:58 -0800 (PST)
From:      John Baldwin <jhb@FreeBSD.org>
To:        current@FreeBSD.org, bde@FreeBSD.org
Subject:   sio patch to use mutexes
Message-ID:  <XFMail.001103141858.jhb@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
Hey all,

Enclosed is a patch to convert the sio driver from using a simplelock and the
*_intr() functions to using a single driver-wide spin mutex.  The patch can
also be found at http://www.FreeBSD.org/~jhb/patches/sio.patch.  Please test
this out and let me know if it breaks anyone's system.

Index: sio.c
===================================================================
RCS file: /usr/cvs/src/sys/isa/sio.c,v
retrieving revision 1.319
diff -u -r1.319 sio.c
--- sio.c       2000/10/25 05:19:37     1.319
+++ sio.c       2000/10/25 18:50:59
@@ -96,12 +96,6 @@
 #endif
 #include <isa/ic/ns16550.h>
 
-/* XXX - this is ok because we only do sio fast interrupts on i386 */
-#ifndef __i386__
-#define disable_intr()
-#define enable_intr()
-#endif
-
 #define        LOTS_OF_EVENTS  64      /* helps separate urgent events from
input */
 
 #define        CALLOUT_MASK            0x80
@@ -323,7 +317,9 @@
 static int     sio_pci_probe __P((device_t dev));
 #endif /* NPCI > 0 */
 
-static char driver_name[] = "sio";
+static char    driver_name[] = "sio";
+static struct  mtx sio_lock;
+static int     sio_inited;
 
 /* table and macro for fast conversion from a unit number to its com struct */
 static devclass_t      sio_devclass;
@@ -761,7 +757,6 @@
        u_int           flags = device_get_flags(dev);
        int             rid;
        struct resource *port;
-       int             intrsave;
 
        rid = xrid;
        port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
@@ -773,6 +768,9 @@
        com->bst = rman_get_bustag(port);
        com->bsh = rman_get_bushandle(port);
 
+       if (atomic_cmpset_int(&sio_inited, 0, 1))
+               mtx_init(&sio_lock, "sio", MTX_SPIN);
+
 #if 0
        /*
         * XXX this is broken - when we are first called, there are no
@@ -858,9 +856,7 @@
         * but mask them in the processor as well in case there are some
         * (misconfigured) shared interrupts.
         */
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&sio_lock, MTX_SPIN);
 /* EXTRA DELAY? */
 
        /*
@@ -957,8 +953,7 @@
                        CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
                }
                sio_setreg(com, com_cfcr, CFCR_8BITS);
-               COM_UNLOCK();
-               restore_intr(intrsave);
+               mtx_exit(&sio_lock, MTX_SPIN);
                bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
                return (iobase == siocniobase ? 0 : result);
        }
@@ -998,8 +993,7 @@
        irqmap[3] = isa_irq_pending();
        failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
 
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&sio_lock, MTX_SPIN);
 
        irqs = irqmap[1] & ~irqmap[0];
        if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
@@ -1118,7 +1112,6 @@
        int             rid;
        struct resource *port;
        int             ret;
-       int             intrstate;
 
        rid = xrid;
        port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
@@ -1187,10 +1180,8 @@
                com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
        } else
                com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
-       intrstate = save_intr();
        if (siosetwater(com, com->it_in.c_ispeed) != 0) {
-               COM_UNLOCK();
-               restore_intr(intrstate);
+               mtx_exit(&sio_lock, MTX_SPIN);
                /*
                 * Leave i/o resources allocated if this is a `cn'-level
                 * console, so that other devices can't snarf them.
@@ -1199,8 +1190,7 @@
                        bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
                return (ENOMEM);
        }
-       COM_UNLOCK();
-       restore_intr(intrstate);
+       mtx_exit(&sio_lock, MTX_SPIN);
        termioschars(&com->it_in);
        com->it_out = com->it_in;
 
@@ -1436,8 +1426,6 @@
                        goto out;
                }
        } else {
-               int     intrsave;
-
                /*
                 * The device isn't open, so there are no conflicts.
                 * Initialize it.  Initialization is done twice in many
@@ -1497,9 +1485,7 @@
                        }
                }
 
-               intrsave = save_intr();
-               disable_intr();
-               COM_LOCK();
+               mtx_enter(&sio_lock, MTX_SPIN);
                (void) inb(com->line_status_port);
                (void) inb(com->data_port);
                com->prev_modem_status = com->last_modem_status
@@ -1511,8 +1497,7 @@
                        outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
                                                | IER_ERLS | IER_EMSC);
                }
-               COM_UNLOCK();
-               restore_intr(intrsave);
+               mtx_exit(&sio_lock, MTX_SPIN);
                /*
                 * Handle initial DCD.  Callout devices get a fake initial
                 * DCD (trapdoor DCD).  If we are callout, then any sleeping
@@ -1734,7 +1719,8 @@
 }
 
 /*
- * Call this function with COM_LOCK.  It will return with the lock still held.
+ * Call this function with the sio_lock mutex held.  It will return with the
+ * lock still held.
  */
 static void
 sioinput(com)
@@ -1745,7 +1731,6 @@
        u_char          line_status;
        int             recv_data;
        struct tty      *tp;
-       int             intrsave;
 
        buf = com->ibuf;
        tp = com->tp;
@@ -1768,9 +1753,7 @@
                         * semantics instead of the save-and-disable semantics
                         * that are used everywhere else.
                         */
-                       intrsave = save_intr();
-                       COM_UNLOCK();
-                       enable_intr();
+                       mtx_exit(&sio_lock, MTX_SPIN);
                        incc = com->iptr - buf;
                        if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
                            && (com->state & CS_RTS_IFLOW
@@ -1791,8 +1774,7 @@
                                tp->t_lflag &= ~FLUSHO;
                                comstart(tp);
                        }
-                       restore_intr(intrsave);
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                } while (buf < com->iptr);
        } else {
                do {
@@ -1801,9 +1783,7 @@
                         * semantics instead of the save-and-disable semantics
                         * that are used everywhere else.
                         */
-                       intrsave = save_intr();
-                       COM_UNLOCK();
-                       enable_intr();
+                       mtx_exit(&sio_lock, MTX_SPIN);
                        line_status = buf[com->ierroff];
                        recv_data = *buf++;
                        if (line_status
@@ -1818,8 +1798,7 @@
                                        recv_data |= TTY_PE;
                        }
                        (*linesw[tp->t_line].l_rint)(recv_data, tp);
-                       restore_intr(intrsave);
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                } while (buf < com->iptr);
        }
        com_events -= (com->iptr - com->ibuf);
@@ -1839,14 +1818,17 @@
 siointr(arg)
        void            *arg;
 {
+       struct com_s    *com;
+
 #ifndef COM_MULTIPORT
-       COM_LOCK();
-       siointr1((struct com_s *) arg);
-       COM_UNLOCK();
+       com = (struct com_s *)arg;
+
+       mtx_enter(&sio_lock, MTX_SPIN);
+       siointr1(com);
+       mtx_exit(&sio_lock, MTX_SPIN);
 #else /* COM_MULTIPORT */
        bool_t          possibly_more_intrs;
        int             unit;
-       struct com_s    *com;
 
        /*
         * Loop until there is no activity on any port.  This is necessary
@@ -1855,7 +1837,7 @@
         * devices, then the edge from one may be lost because another is
         * on.
         */
-       COM_LOCK();
+       mtx_enter(&sio_lock, MTX_SPIN);
        do {
                possibly_more_intrs = FALSE;
                for (unit = 0; unit < sio_numunits; ++unit) {
@@ -1874,7 +1856,7 @@
                        /* XXX COM_UNLOCK(); */
                }
        } while (possibly_more_intrs);
-       COM_UNLOCK();
+       mtx_exit(&sio_lock, MTX_SPIN);
 #endif /* COM_MULTIPORT */
 }
 
@@ -2264,7 +2246,6 @@
 siopoll(void *dummy)
 {
        int             unit;
-       int             intrsave;
 
        if (com_events == 0)
                return;
@@ -2283,9 +2264,7 @@
                         * Discard any events related to never-opened or
                         * going-away devices.
                         */
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                        incc = com->iptr - com->ibuf;
                        com->iptr = com->ibuf;
                        if (com->state & CS_CHECKMSR) {
@@ -2293,43 +2272,33 @@
                                com->state &= ~CS_CHECKMSR;
                        }
                        com_events -= incc;
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&sio_lock, MTX_SPIN);
                        continue;
                }
                if (com->iptr != com->ibuf) {
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                        sioinput(com);
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&sio_lock, MTX_SPIN);
                }
                if (com->state & CS_CHECKMSR) {
                        u_char  delta_modem_status;
 
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                        delta_modem_status = com->last_modem_status
                                             ^ com->prev_modem_status;
                        com->prev_modem_status = com->last_modem_status;
                        com_events -= LOTS_OF_EVENTS;
                        com->state &= ~CS_CHECKMSR;
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&sio_lock, MTX_SPIN);
                        if (delta_modem_status & MSR_DCD)
                                (*linesw[tp->t_line].l_modem)
                                        (tp, com->prev_modem_status & MSR_DCD);
                }
                if (com->state & CS_ODONE) {
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                        com_events -= LOTS_OF_EVENTS;
                        com->state &= ~CS_ODONE;
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&sio_lock, MTX_SPIN);
                        if (!(com->state & CS_BUSY)
                            && !(com->extra_state & CSE_BUSYCHECK)) {
                                timeout(siobusycheck, com, hz / 100);
@@ -2357,7 +2326,6 @@
        u_char          dlbl;
        int             s;
        int             unit;
-       int             intrsave;
 
        /* do historical conversions */
        if (t->c_ispeed == 0)
@@ -2429,7 +2397,6 @@
         * the speed change atomically.  Keeping interrupts disabled is
         * especially important while com_data is hidden.
         */
-       intrsave = save_intr();
        (void) siosetwater(com, t->c_ispeed);
 
        if (divisor != 0) {
@@ -2517,8 +2484,7 @@
        if (com->state >= (CS_BUSY | CS_TTGO))
                siointr1(com);
 
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&sio_lock, MTX_SPIN);
        splx(s);
        comstart(tp);
        if (com->ibufold != NULL) {
@@ -2529,8 +2495,8 @@
 }
 
 /*
- * This function must be called with interrupts enabled and the com_lock
- * unlocked.  It will return with interrupts disabled and the com_lock locked.
+ * This function must be called with the sio_lock mutex released and will
+ * return with it obtained.
  */
 static int
 siosetwater(com, speed)
@@ -2552,8 +2518,7 @@
        for (ibufsize = 128; ibufsize < cp4ticks;)
                ibufsize <<= 1;
        if (ibufsize == com->ibufsize) {
-               disable_intr();
-               COM_LOCK();
+               mtx_enter(&sio_lock, MTX_SPIN);
                return (0);
        }
 
@@ -2563,8 +2528,7 @@
         */
        ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
        if (ibuf == NULL) {
-               disable_intr();
-               COM_LOCK();
+               mtx_enter(&sio_lock, MTX_SPIN);
                return (ENOMEM);
        }
 
@@ -2582,8 +2546,7 @@
         * Read current input buffer, if any.  Continue with interrupts
         * disabled.
         */
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&sio_lock, MTX_SPIN);
        if (com->iptr != com->ibuf)
                sioinput(com);
 
@@ -2612,16 +2575,13 @@
        struct com_s    *com;
        int             s;
        int             unit;
-       int             intrsave;
 
        unit = DEV_TO_UNIT(tp->t_dev);
        com = com_addr(unit);
        if (com == NULL)
                return;
        s = spltty();
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&sio_lock, MTX_SPIN);
        if (tp->t_state & TS_TTSTOP)
                com->state &= ~CS_TTGO;
        else
@@ -2634,8 +2594,7 @@
                    && com->state & CS_RTS_IFLOW)
                        outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
        }
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&sio_lock, MTX_SPIN);
        if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
                ttwwakeup(tp);
                splx(s);
@@ -2651,9 +2610,7 @@
                                                  sizeof com->obuf1);
                        com->obufs[0].l_next = NULL;
                        com->obufs[0].l_queued = TRUE;
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                        if (com->state & CS_BUSY) {
                                qp = com->obufq.l_next;
                                while ((next = qp->l_next) != NULL)
@@ -2665,8 +2622,7 @@
                                com->obufq.l_next = &com->obufs[0];
                                com->state |= CS_BUSY;
                        }
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&sio_lock, MTX_SPIN);
                }
                if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
                        com->obufs[1].l_tail
@@ -2674,9 +2630,7 @@
                                                  sizeof com->obuf2);
                        com->obufs[1].l_next = NULL;
                        com->obufs[1].l_queued = TRUE;
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                        if (com->state & CS_BUSY) {
                                qp = com->obufq.l_next;
                                while ((next = qp->l_next) != NULL)
@@ -2688,18 +2642,14 @@
                                com->obufq.l_next = &com->obufs[1];
                                com->state |= CS_BUSY;
                        }
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&sio_lock, MTX_SPIN);
                }
                tp->t_state |= TS_BUSY;
        }
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&sio_lock, MTX_SPIN);
        if (com->state >= (CS_BUSY | CS_TTGO))
                siointr1(com);  /* fake interrupt to start output */
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&sio_lock, MTX_SPIN);
        ttwwakeup(tp);
        splx(s);
 }
@@ -2710,14 +2660,11 @@
        int             rw;
 {
        struct com_s    *com;
-       int             intrsave;
 
        com = com_addr(DEV_TO_UNIT(tp->t_dev));
        if (com == NULL || com->gone)
                return;
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&sio_lock, MTX_SPIN);
        if (rw & FWRITE) {
                if (com->hasfifo)
 #ifdef COM_ESP
@@ -2744,8 +2691,7 @@
                com_events -= (com->iptr - com->ibuf);
                com->iptr = com->ibuf;
        }
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&sio_lock, MTX_SPIN);
        comstart(tp);
 }
 
@@ -2757,7 +2703,6 @@
 {
        int     mcr;
        int     msr;
-       int     intrsave;
 
        if (how == DMGET) {
                bits = TIOCM_LE;        /* XXX - always enabled while open */
@@ -2789,9 +2734,7 @@
                mcr |= MCR_RTS;
        if (com->gone)
                return(0);
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&sio_lock, MTX_SPIN);
        switch (how) {
        case DMSET:
                outb(com->modem_ctl_port,
@@ -2804,8 +2747,7 @@
                outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
                break;
        }
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&sio_lock, MTX_SPIN);
        return (0);
 }
 
@@ -2853,7 +2795,6 @@
 {
        struct com_s    *com;
        int             unit;
-       int             intrsave;
 
        sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
 
@@ -2865,12 +2806,9 @@
                com = com_addr(unit);
                if (com != NULL && !com->gone
                    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                        siointr1(com);
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&sio_lock, MTX_SPIN);
                }
        }
 
@@ -2892,13 +2830,10 @@
                        u_int   delta;
                        u_long  total;
 
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&sio_lock, MTX_SPIN);
                        delta = com->delta_error_counts[errnum];
                        com->delta_error_counts[errnum] = 0;
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&sio_lock, MTX_SPIN);
                        if (delta == 0)
                                continue;
                        total = com->error_counts[errnum] += delta;



-- 

John Baldwin <jhb@FreeBSD.org> -- http://www.FreeBSD.org/~jhb/
PGP Key: http://www.baldwin.cx/~john/pgpkey.asc
"Power Users Use the Power to Serve!"  -  http://www.FreeBSD.org/


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?XFMail.001103141858.jhb>