summaryrefslogtreecommitdiffstats
path: root/sys/isa
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2000-12-18 23:56:16 +0000
committerjhb <jhb@FreeBSD.org>2000-12-18 23:56:16 +0000
commit66a2ef9e856b06195649a56b3fdc8e0425f8455a (patch)
tree4a93316a742a32c891edfd65c151124e53235e22 /sys/isa
parent4423d75eace68c7348f9a8630453cd39703a962c (diff)
downloadFreeBSD-src-66a2ef9e856b06195649a56b3fdc8e0425f8455a.zip
FreeBSD-src-66a2ef9e856b06195649a56b3fdc8e0425f8455a.tar.gz
Convert the sio driver to use a spin mutex instead of a s_lock. This is
going to hurt sio(4) performance for the time being. As we get closer to release and have more of the kernel unlocked we can come back to doing arcane optimizations to workaround the limitations of the sio hardware.
Diffstat (limited to 'sys/isa')
-rw-r--r--sys/isa/sio.c181
1 files changed, 58 insertions, 123 deletions
diff --git a/sys/isa/sio.c b/sys/isa/sio.c
index 4dc22ea..9b9fc97 100644
--- a/sys/isa/sio.c
+++ b/sys/isa/sio.c
@@ -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 void sio_pci_kludge_unit __P((device_t dev));
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 @@ sioprobe(dev, xrid)
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 @@ sioprobe(dev, xrid)
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 @@ sioprobe(dev, xrid)
* 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 @@ sioprobe(dev, xrid)
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 @@ sioprobe(dev, xrid)
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 @@ sioattach(dev, xrid)
int rid;
struct resource *port;
int ret;
- int intrstate;
rid = xrid;
port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
@@ -1187,10 +1180,8 @@ sioattach(dev, xrid)
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 @@ sioattach(dev, xrid)
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 @@ open_top:
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 @@ open_top:
}
}
- 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 @@ open_top:
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 @@ siodtrwakeup(chan)
}
/*
- * 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 @@ sioinput(com)
u_char line_status;
int recv_data;
struct tty *tp;
- int intrsave;
buf = com->ibuf;
tp = com->tp;
@@ -1768,9 +1753,7 @@ sioinput(com)
* 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 @@ sioinput(com)
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 @@ sioinput(com)
* 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 @@ sioinput(com)
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 @@ void
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 @@ siointr(arg)
* 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 @@ siointr(arg)
/* XXX COM_UNLOCK(); */
}
} while (possibly_more_intrs);
- COM_UNLOCK();
+ mtx_exit(&sio_lock, MTX_SPIN);
#endif /* COM_MULTIPORT */
}
@@ -2264,7 +2246,6 @@ static void
siopoll(void *dummy)
{
int unit;
- int intrsave;
if (com_events == 0)
return;
@@ -2283,9 +2264,7 @@ repeat:
* 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 @@ repeat:
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 @@ comparam(tp, t)
u_char dlbl;
int s;
int unit;
- int intrsave;
/* do historical conversions */
if (t->c_ispeed == 0)
@@ -2429,7 +2397,6 @@ comparam(tp, t)
* 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 @@ comparam(tp, t)
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 @@ comparam(tp, t)
}
/*
- * 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 @@ siosetwater(com, speed)
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 @@ siosetwater(com, speed)
*/
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 @@ siosetwater(com, speed)
* 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 @@ comstart(tp)
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 @@ comstart(tp)
&& 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 @@ comstart(tp)
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 @@ comstart(tp)
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 @@ comstart(tp)
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 @@ comstart(tp)
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 @@ comstop(tp, rw)
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 @@ comstop(tp, rw)
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 @@ commctl(com, bits, how)
{
int mcr;
int msr;
- int intrsave;
if (how == DMGET) {
bits = TIOCM_LE; /* XXX - always enabled while open */
@@ -2789,9 +2734,7 @@ commctl(com, bits, how)
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 @@ commctl(com, bits, how)
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 @@ comwakeup(chan)
{
struct com_s *com;
int unit;
- int intrsave;
sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
@@ -2865,12 +2806,9 @@ comwakeup(chan)
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 @@ comwakeup(chan)
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;
OpenPOWER on IntegriCloud