Date: Mon, 09 Oct 2000 12:30:32 -0700 (PDT) From: John Baldwin <jhb@FreeBSD.org> To: bde@FreeBSD.org, current@FreeBSD.org Subject: sio patch to add mutexes.. Message-ID: <XFMail.001009123032.jhb@FreeBSD.org>
next in thread | raw e-mail | index | archive | help
Hey gang, I have some patches to add per-softc spin mutexes to the sio code in place of the old COM_LOCK. Since spin mutexes already dink with interrupts, this also allows all the *_intr() cruft to go away. Unfortunately, I can't get the current sio to work on any of the boxes here because DCD is never raised, so I don't know if this breaks anything, though it doesn't seem to fix my bxoes. :-/ The patch is availabe at http://www.FreeBSD.org/~jhb/patches/sio.patch, and included inline here for those w/o web access: Index: sio.c =================================================================== RCS file: /home/ncvs/src/sys/isa/sio.c,v retrieving revision 1.316 diff -u -r1.316 sio.c --- sio.c 2000/10/05 23:09:54 1.316 +++ sio.c 2000/10/06 06:11:29 @@ -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 @@ -284,6 +278,8 @@ */ u_char obuf1[256]; u_char obuf2[256]; + + struct mtx intrlock; /* spin mutex used in the interrupt handler */ }; #ifdef COM_ESP @@ -759,7 +755,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, @@ -771,6 +766,7 @@ com->bst = rman_get_bustag(port); com->bsh = rman_get_bushandle(port); + mtx_init(&com->intrlock, "sio interrupt lock", MTX_SPIN); #if 0 /* * XXX this is broken - when we are first called, there are no @@ -856,9 +852,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(&com->intrlock, MTX_SPIN); /* EXTRA DELAY? */ /* @@ -955,9 +949,9 @@ CLR_FLAG(dev, COM_C_IIR_TXRDYBUG); } sio_setreg(com, com_cfcr, CFCR_8BITS); - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); bus_release_resource(dev, SYS_RES_IOPORT, rid, port); + mtx_destroy(&com->intrlock); return (iobase == siocniobase ? 0 : result); } @@ -996,8 +990,7 @@ irqmap[3] = isa_irq_pending(); failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND; - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); irqs = irqmap[1] & ~irqmap[0]; if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 && @@ -1026,6 +1019,7 @@ break; } bus_release_resource(dev, SYS_RES_IOPORT, rid, port); + mtx_destroy(&com->intrlock); return (iobase == siocniobase ? 0 : result); } @@ -1116,7 +1110,6 @@ int rid; struct resource *port; int ret; - int intrstate; rid = xrid; port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, @@ -1155,6 +1148,7 @@ com->tx_fifo_size = 1; com->obufs[0].l_head = com->obuf1; com->obufs[1].l_head = com->obuf2; + mtx_init(&com->intrlock, "sio interrupt lock", MTX_SPIN); com->data_port = iobase + com_data; com->int_id_port = iobase + com_iir; @@ -1185,10 +1179,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(&com->intrlock, MTX_SPIN); /* * Leave i/o resources allocated if this is a `cn'-level * console, so that other devices can't snarf them. @@ -1197,8 +1189,7 @@ bus_release_resource(dev, SYS_RES_IOPORT, rid, port); return (ENOMEM); } - COM_UNLOCK(); - restore_intr(intrstate); + mtx_exit(&com->intrlock, MTX_SPIN); termioschars(&com->it_in); com->it_out = com->it_in; @@ -1432,8 +1423,6 @@ goto out; } } else { - int intrsave; - /* * The device isn't open, so there are no conflicts. * Initialize it. Initialization is done twice in many @@ -1493,9 +1482,7 @@ } } - intrsave = save_intr(); - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); (void) inb(com->line_status_port); (void) inb(com->data_port); com->prev_modem_status = com->last_modem_status @@ -1507,8 +1494,7 @@ outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC); } - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); /* * Handle initial DCD. Callout devices get a fake initial * DCD (trapdoor DCD). If we are callout, then any sleeping @@ -1730,7 +1716,8 @@ } /* - * Call this function with COM_LOCK. It will return with the lock still held. + * Call this function with the per-softc intrlock mutex held. It will return + * with the lock still held. */ static void sioinput(com) @@ -1741,7 +1728,6 @@ u_char line_status; int recv_data; struct tty *tp; - int intrsave; buf = com->ibuf; tp = com->tp; @@ -1764,9 +1750,7 @@ * semantics instead of the save-and-disable semantics * that are used everywhere else. */ - intrsave = save_intr(); - COM_UNLOCK(); - enable_intr(); + mtx_exit(&com->intrlock, MTX_SPIN); incc = com->iptr - buf; if (tp->t_rawq.c_cc + incc > tp->t_ihiwat && (com->state & CS_RTS_IFLOW @@ -1787,8 +1771,7 @@ tp->t_lflag &= ~FLUSHO; comstart(tp); } - restore_intr(intrsave); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); } while (buf < com->iptr); } else { do { @@ -1797,9 +1780,7 @@ * semantics instead of the save-and-disable semantics * that are used everywhere else. */ - intrsave = save_intr(); - COM_UNLOCK(); - enable_intr(); + mtx_exit(&com->intrlock, MTX_SPIN); line_status = buf[com->ierroff]; recv_data = *buf++; if (line_status @@ -1814,8 +1795,7 @@ recv_data |= TTY_PE; } (*linesw[tp->t_line].l_rint)(recv_data, tp); - restore_intr(intrsave); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); } while (buf < com->iptr); } com_events -= (com->iptr - com->ibuf); @@ -1835,14 +1815,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(&com->intrlock, MTX_SPIN); + siointr1(com); + mtx_exit(&com->intrlock, 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 @@ -1851,15 +1834,11 @@ * devices, then the edge from one may be lost because another is * on. */ - COM_LOCK(); do { possibly_more_intrs = FALSE; for (unit = 0; unit < sio_numunits; ++unit) { com = com_addr(unit); - /* - * XXX COM_LOCK(); - * would it work here, or be counter-productive? - */ + mtx_enter(&com->intrlock, MTX_SPIN); if (com != NULL && !com->gone && (inb(com->int_id_port) & IIR_IMASK) @@ -1867,10 +1846,9 @@ siointr1(com); possibly_more_intrs = TRUE; } - /* XXX COM_UNLOCK(); */ + mtx_exit(&com->intrlock, MTX_SPIN); } } while (possibly_more_intrs); - COM_UNLOCK(); #endif /* COM_MULTIPORT */ } @@ -2264,7 +2242,6 @@ siopoll() { int unit; - int intrsave; if (com_events == 0) return; @@ -2283,9 +2260,7 @@ * Discard any events related to never-opened or * going-away devices. */ - intrsave = save_intr(); - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); incc = com->iptr - com->ibuf; com->iptr = com->ibuf; if (com->state & CS_CHECKMSR) { @@ -2293,43 +2268,33 @@ com->state &= ~CS_CHECKMSR; } com_events -= incc; - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); continue; } if (com->iptr != com->ibuf) { - intrsave = save_intr(); - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); sioinput(com); - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); } if (com->state & CS_CHECKMSR) { u_char delta_modem_status; - intrsave = save_intr(); - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, 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(&com->intrlock, 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(&com->intrlock, MTX_SPIN); com_events -= LOTS_OF_EVENTS; com->state &= ~CS_ODONE; - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); if (!(com->state & CS_BUSY) && !(com->extra_state & CSE_BUSYCHECK)) { timeout(siobusycheck, com, hz / 100); @@ -2357,7 +2322,6 @@ u_char dlbl; int s; int unit; - int intrsave; /* do historical conversions */ if (t->c_ispeed == 0) @@ -2429,7 +2393,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 +2480,7 @@ if (com->state >= (CS_BUSY | CS_TTGO)) siointr1(com); - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); splx(s); comstart(tp); if (com->ibufold != NULL) { @@ -2529,8 +2491,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 per-softc interrupt mutex released + * and will return with it obtained. */ static int siosetwater(com, speed) @@ -2552,8 +2514,7 @@ for (ibufsize = 128; ibufsize < cp4ticks;) ibufsize <<= 1; if (ibufsize == com->ibufsize) { - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); return (0); } @@ -2563,8 +2524,7 @@ */ ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); if (ibuf == NULL) { - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); return (ENOMEM); } @@ -2582,8 +2542,7 @@ * Read current input buffer, if any. Continue with interrupts * disabled. */ - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); if (com->iptr != com->ibuf) sioinput(com); @@ -2612,16 +2571,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(&com->intrlock, MTX_SPIN); if (tp->t_state & TS_TTSTOP) com->state &= ~CS_TTGO; else @@ -2634,8 +2590,7 @@ && com->state & CS_RTS_IFLOW) outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); } - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { ttwwakeup(tp); splx(s); @@ -2651,9 +2606,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(&com->intrlock, MTX_SPIN); if (com->state & CS_BUSY) { qp = com->obufq.l_next; while ((next = qp->l_next) != NULL) @@ -2665,8 +2618,7 @@ com->obufq.l_next = &com->obufs[0]; com->state |= CS_BUSY; } - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); } if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { com->obufs[1].l_tail @@ -2674,9 +2626,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(&com->intrlock, MTX_SPIN); if (com->state & CS_BUSY) { qp = com->obufq.l_next; while ((next = qp->l_next) != NULL) @@ -2688,18 +2638,14 @@ com->obufq.l_next = &com->obufs[1]; com->state |= CS_BUSY; } - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); } tp->t_state |= TS_BUSY; } - intrsave = save_intr(); - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); if (com->state >= (CS_BUSY | CS_TTGO)) siointr1(com); /* fake interrupt to start output */ - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); ttwwakeup(tp); splx(s); } @@ -2710,14 +2656,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(&com->intrlock, MTX_SPIN); if (rw & FWRITE) { if (com->hasfifo) #ifdef COM_ESP @@ -2744,8 +2687,7 @@ com_events -= (com->iptr - com->ibuf); com->iptr = com->ibuf; } - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); comstart(tp); } @@ -2757,7 +2699,6 @@ { int mcr; int msr; - int intrsave; if (how == DMGET) { bits = TIOCM_LE; /* XXX - always enabled while open */ @@ -2789,9 +2730,7 @@ mcr |= MCR_RTS; if (com->gone) return(0); - intrsave = save_intr(); - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); switch (how) { case DMSET: outb(com->modem_ctl_port, @@ -2804,8 +2743,7 @@ outb(com->modem_ctl_port, com->mcr_image &= ~mcr); break; } - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); return (0); } @@ -2853,7 +2791,6 @@ { struct com_s *com; int unit; - int intrsave; sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout); @@ -2865,12 +2802,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(&com->intrlock, MTX_SPIN); siointr1(com); - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, MTX_SPIN); } } @@ -2892,13 +2826,10 @@ u_int delta; u_long total; - intrsave = save_intr(); - disable_intr(); - COM_LOCK(); + mtx_enter(&com->intrlock, MTX_SPIN); delta = com->delta_error_counts[errnum]; com->delta_error_counts[errnum] = 0; - COM_UNLOCK(); - restore_intr(intrsave); + mtx_exit(&com->intrlock, 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.001009123032.jhb>