From owner-freebsd-current Fri Nov 3 14:18:54 2000 Delivered-To: freebsd-current@freebsd.org Received: from pike.osd.bsdi.com (pike.osd.bsdi.com [204.216.28.222]) by hub.freebsd.org (Postfix) with ESMTP id 54F6437B4CF; Fri, 3 Nov 2000 14:18:41 -0800 (PST) Received: from laptop.baldwin.cx (john@dhcp241.osd.bsdi.com [204.216.28.241]) by pike.osd.bsdi.com (8.11.0/8.9.3) with ESMTP id eA3MIYH40642; Fri, 3 Nov 2000 14:18:34 -0800 (PST) (envelope-from jhb@FreeBSD.org) Message-ID: X-Mailer: XFMail 1.4.0 on FreeBSD X-Priority: 3 (Normal) Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Date: Fri, 03 Nov 2000 14:18:58 -0800 (PST) From: John Baldwin To: current@FreeBSD.org, bde@FreeBSD.org Subject: sio patch to use mutexes Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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 -/* 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 -- 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