diff options
author | jhb <jhb@FreeBSD.org> | 2001-02-09 17:53:23 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-02-09 17:53:23 +0000 |
commit | 4444722abea8ce2ec79adbb75aaac0d6e63bf8e0 (patch) | |
tree | 8109f2a5f60ddf0d2e21a8297fd682b60e0060c5 /sys/alpha | |
parent | 1667b748b0a4f26cef857dc41e601a34b06cb4b6 (diff) | |
download | FreeBSD-src-4444722abea8ce2ec79adbb75aaac0d6e63bf8e0.zip FreeBSD-src-4444722abea8ce2ec79adbb75aaac0d6e63bf8e0.tar.gz |
Use the MI ithread helper functions in the alpha hardware interrupt code.
Diffstat (limited to 'sys/alpha')
-rw-r--r-- | sys/alpha/alpha/interrupt.c | 291 | ||||
-rw-r--r-- | sys/alpha/include/intr.h | 11 | ||||
-rw-r--r-- | sys/alpha/isa/isa.c | 3 | ||||
-rw-r--r-- | sys/alpha/mcbus/mcpcia.c | 5 | ||||
-rw-r--r-- | sys/alpha/pci/apecs.c | 3 | ||||
-rw-r--r-- | sys/alpha/pci/cia.c | 3 | ||||
-rw-r--r-- | sys/alpha/pci/t2.c | 5 | ||||
-rw-r--r-- | sys/alpha/pci/tsunami.c | 3 | ||||
-rw-r--r-- | sys/alpha/tlsb/dwlpx.c | 5 |
9 files changed, 63 insertions, 266 deletions
diff --git a/sys/alpha/alpha/interrupt.c b/sys/alpha/alpha/interrupt.c index f2b431f..a6a6555 100644 --- a/sys/alpha/alpha/interrupt.c +++ b/sys/alpha/alpha/interrupt.c @@ -48,6 +48,7 @@ #include <sys/malloc.h> #include <sys/interrupt.h> #include <sys/ipl.h> +#include <sys/kernel.h> #include <sys/kthread.h> #include <sys/ktr.h> #include <sys/mutex.h> @@ -82,7 +83,6 @@ void (*perf_irq)(unsigned long, struct trapframe *) = dummy_perf; static u_int schedclk2; -static void ithd_loop(void *); static driver_intr_t alpha_clock_interrupt; void @@ -322,180 +322,72 @@ struct alpha_intr { int vector; /* vector to match */ struct ithd *ithd; /* interrupt thread */ volatile long *cntp; /* interrupt counter */ - void (*disable)(int); /* disable source */ - void (*enable)(int); /* enable source */ }; +static struct mtx alpha_intr_hash_lock; static struct alpha_intr_list alpha_intr_hash[31]; +static void ithds_init(void *dummy); + +static void +ithds_init(void *dummy) +{ + + mtx_init(&alpha_intr_hash_lock, "ithread table lock", MTX_SPIN); +} +SYSINIT(ithds_init, SI_SUB_INTR, SI_ORDER_SECOND, ithds_init, NULL); + int -alpha_setup_intr(const char *name, int vector, driver_intr_t *handler, - void *arg, int pri, int flags, void **cookiep, - volatile long *cntp, void (*disable)(int), void (*enable)(int)) +alpha_setup_intr(const char *name, int vector, driver_intr_t handler, void *arg, + enum intr_type flags, void **cookiep, volatile long *cntp, + void (*disable)(int), void (*enable)(int)) { int h = HASHVEC(vector); struct alpha_intr *i; - struct intrhand *head, *idesc; - struct ithd *ithd; - struct proc *p; - int s, errcode; + int errcode; + /* + * XXX - Can we have more than one device on a vector? If so, we have + * a race condition here that needs to be worked around similar to + * the fashion done in the i386 inthand_add() function. + */ + /* First, check for an existing hash table entry for this vector. */ + mtx_lock_spin(&alpha_intr_hash_lock); for (i = LIST_FIRST(&alpha_intr_hash[h]); i && i->vector != vector; i = LIST_NEXT(i, list)) ; /* nothing */ + mtx_unlock_spin(&alpha_intr_hash_lock); + if (i == NULL) { /* None was found, so create an entry. */ i = malloc(sizeof(struct alpha_intr), M_DEVBUF, M_NOWAIT); if (i == NULL) return ENOMEM; i->vector = vector; - i->ithd = NULL; i->cntp = cntp; - i->disable = disable; - i->enable = enable; - - s = save_intr(); - disable_intr(); - LIST_INSERT_HEAD(&alpha_intr_hash[h], i, list); - restore_intr(s); - } - - /* Second, create the interrupt thread if needed. */ - ithd = i->ithd; - if (ithd == NULL || ithd->it_ih == NULL) { - /* first handler for this vector */ - if (ithd == NULL) { - ithd = malloc(sizeof(struct ithd), M_DEVBUF, - M_WAITOK | M_ZERO); - if (ithd == NULL) - return ENOMEM; - - ithd->irq = vector; - ithd->it_md = i; - i->ithd = ithd; + errcode = ithread_create(&i->ithd, vector, 0, disable, enable, + "intr:"); + if (errcode) { + free(i, M_DEVBUF); + return errcode; } - /* Create a kernel thread if needed. */ - if ((flags & INTR_FAST) == 0) { - if (ithd->it_proc == NULL) { - errcode = kthread_create(ithd_loop, NULL, &p, - RFSTOPPED | RFHIGHPID, "intr: %s", name); - if (errcode) - panic( - "alpha_setup_intr: Can't create interrupt thread"); - p->p_rtprio.type = RTP_PRIO_ITHREAD; - p->p_stat = SWAIT; /* we're idle */ - - /* Put in linkages. */ - ithd->it_proc = p; - p->p_ithd = ithd; - } else - snprintf(ithd->it_proc->p_comm, MAXCOMLEN, - "intr: %s", name); - p->p_rtprio.prio = pri; - } - } else if ((flags & INTR_EXCL) != 0 || - (ithd->it_ih->ih_flags & INTR_EXCL) != 0) { - /* - * We can't have more than one exclusive handler for a given - * interrupt. - */ - if (bootverbose) - printf( - "\tdevice combination %s and %s doesn't support shared vector %x\n", - ithd->it_ih->ih_name, name, vector); - return EINVAL; - } else if ((flags & INTR_FAST) != 0) { - /* We can only have one fast interrupt by itself. */ - if (bootverbose) - printf( - "\tCan't add fast interrupt %s to normal interrupt %s on vector %x\n", - name, ithd->it_ih->ih_name, vector); - return EINVAL; - } else if (ithd->it_proc == NULL) { - if (bootverbose) - printf( - "\tCan't add normal interrupt %s to fast interrupt %s on vector %x\n", - name, ithd->it_ih->ih_name, vector); - return EINVAL; - } else { - p = ithd->it_proc; - if (strlen(p->p_comm) + strlen(name) < MAXCOMLEN) { - strcat(p->p_comm, " "); - strcat(p->p_comm, name); - } else if (strlen(p->p_comm) == MAXCOMLEN) - p->p_comm[MAXCOMLEN - 1] = '+'; - else - strcat(p->p_comm, "+"); + mtx_lock_spin(&alpha_intr_hash_lock); + LIST_INSERT_HEAD(&alpha_intr_hash[h], i, list); + mtx_unlock_spin(&alpha_intr_hash_lock); } - /* Third, setup the interrupt descriptor for this handler. */ - idesc = malloc(sizeof (struct intrhand), M_DEVBUF, M_WAITOK | M_ZERO); - if (idesc == NULL) - return ENOMEM; - - idesc->ih_handler = handler; - idesc->ih_argument = arg; - idesc->ih_flags = flags; - idesc->ih_name = malloc(strlen(name) + 1, M_DEVBUF, M_WAITOK); - if (idesc->ih_name == NULL) { - free(idesc, M_DEVBUF); - return(NULL); - } - strcpy(idesc->ih_name, name); - - /* Fourth, add our handler to the end of the ithread's handler list. */ - head = ithd->it_ih; - if (head) { - while (head->ih_next != NULL) - head = head->ih_next; - head->ih_next = idesc; - } else - ithd->it_ih = idesc; - - *cookiep = idesc; - return 0; + /* Second, add this handler. */ + return (ithread_add_handler(i->ithd, name, handler, arg, + ithread_priority(flags), flags, cookiep)); } int alpha_teardown_intr(void *cookie) { - struct intrhand *idesc = cookie; - struct ithd *ithd; - struct intrhand *head; -#if 0 - struct alpha_intr *i; - int s; -#endif - /* First, detach ourself from our interrupt thread. */ - ithd = idesc->ih_ithd; - KASSERT(ithd != NULL, ("idesc without an interrupt thread")); - - head = ithd->it_ih; - if (head == idesc) - ithd->it_ih = idesc->ih_next; - else { - while (head != NULL && head->ih_next != idesc) - head = head->ih_next; - if (head == NULL) - return (-1); /* couldn't find ourself */ - head->ih_next = idesc->ih_next; - } - free(idesc, M_DEVBUF); - - /* XXX - if the ithd has no handlers left, we should remove it */ - -#if 0 - s = save_intr(); - disable_intr(); - LIST_REMOVE(i, list); - restore_intr(s); - - free(i, M_DEVBUF); -#endif - return 0; + return (ithread_remove_handler(cookie)); } void @@ -504,7 +396,7 @@ alpha_dispatch_intr(void *frame, unsigned long vector) int h = HASHVEC(vector); struct alpha_intr *i; struct ithd *ithd; /* our interrupt thread */ - int saveintr; + struct intrhand *ih; /* * Walk the hash bucket for this vector looking for this vector's @@ -520,10 +412,10 @@ alpha_dispatch_intr(void *frame, unsigned long vector) KASSERT(ithd != NULL, ("interrupt vector without a thread")); /* - * As an optomization until we have kthread_cancel(), if an ithread - * has no handlers, don't schedule it to run. + * As an optomization, if an ithread has no handlers, don't + * schedule it to run. */ - if (ithd->it_ih == NULL) + if (TAILQ_EMPTY(&ithd->it_handlers)) return; atomic_add_long(i->cntp, 1); @@ -533,18 +425,13 @@ alpha_dispatch_intr(void *frame, unsigned long vector) * interrupt by calling the handler directly without Giant. Note * that this means that any fast interrupt handler must be MP safe. */ - if (ithd->it_proc == NULL) { - KASSERT((ithd->it_ih->ih_flags & INTR_FAST) != 0, - ("threaded interrupt without a thread")); - KASSERT(ithd->it_ih->ih_next == NULL, - ("fast interrupt with more than one handler")); - - ithd->it_ih->ih_handler(ithd->it_ih->ih_argument); - + ih = TAILQ_FIRST(&ithd->it_handlers); + if ((ih->ih_flags & INTR_FAST) != 0) { + ih->ih_handler(ih->ih_argument); return; } - CTR3(KTR_INTR, "sched_ithd pid %d(%s) need=%d", + CTR3(KTR_INTR, "alpha_dispatch_intr: pid %d(%s) need=%d", ithd->it_proc->p_pid, ithd->it_proc->p_comm, ithd->it_need); /* @@ -555,10 +442,10 @@ alpha_dispatch_intr(void *frame, unsigned long vector) * is higher priority than their current thread, it gets run now. */ ithd->it_need = 1; - if (i->disable) { + if (ithd->it_disable) { CTR1(KTR_INTR, "alpha_dispatch_intr: disabling vector 0x%x", i->vector); - i->disable(i->vector); + ithd->it_disable(ithd->it_vector); } mtx_lock_spin(&sched_lock); if (ithd->it_proc->p_stat == SWAIT) { @@ -566,98 +453,16 @@ alpha_dispatch_intr(void *frame, unsigned long vector) CTR1(KTR_INTR, "alpha_dispatch_intr: setrunqueue %d", ithd->it_proc->p_pid); - alpha_mb(); /* XXX - ??? */ + alpha_mb(); /* XXX - this is bogus, mtx_lock_spin has a barrier */ ithd->it_proc->p_stat = SRUN; setrunqueue(ithd->it_proc); -#ifdef PREEMPTION - /* Does not work on 4100 and PC164 */ - if (!cold) { - saveintr = sched_lock.mtx_saveintr; - sched_lock.mtx_saveintr = ALPHA_PSL_IPL_0; - if (curproc != PCPU_GET(idleproc)) - setrunqueue(curproc); - mi_switch(); - sched_lock.mtx_saveintr = saveintr; - } -#else need_resched(); -#endif } else { CTR3(KTR_INTR, "alpha_dispatch_intr: %d: it_need %d, state %d", ithd->it_proc->p_pid, ithd->it_need, ithd->it_proc->p_stat); - need_resched(); } mtx_unlock_spin(&sched_lock); } - -void -ithd_loop(void *dummy) -{ - struct ithd *ithd; /* our thread context */ - struct intrhand *ih; /* list of handlers */ - struct alpha_intr *i; /* interrupt source */ - - ithd = curproc->p_ithd; - i = ithd->it_md; - - /* - * As long as we have interrupts outstanding, go through the - * list of handlers, giving each one a go at it. - */ - for (;;) { - CTR3(KTR_INTR, "ithd_loop pid %d(%s) need=%d", - ithd->it_proc->p_pid, ithd->it_proc->p_comm, ithd->it_need); - while (ithd->it_need) { - /* - * Service interrupts. If another interrupt - * arrives while we are running, they will set - * it_need to denote that we should make - * another pass. - */ - ithd->it_need = 0; - - alpha_wmb(); /* push out "it_need=0" */ - - for (ih = ithd->it_ih; ih != NULL; ih = ih->ih_next) { - CTR5(KTR_INTR, - "ithd_loop pid %d ih=%p: %p(%p) flg=%x", - ithd->it_proc->p_pid, (void *)ih, - (void *)ih->ih_handler, ih->ih_argument, - ih->ih_flags); - - if ((ih->ih_flags & INTR_MPSAFE) == 0) - mtx_lock(&Giant); - ih->ih_handler(ih->ih_argument); - if ((ih->ih_flags & INTR_MPSAFE) == 0) - mtx_unlock(&Giant); - } - - /* - * Reenable the source to give it a chance to - * set it_need again. - */ - if (i->enable) - i->enable(i->vector); - } - - /* - * Processed all our interrupts. Now get the sched - * lock. This may take a while and it_need may get - * set again, so we have to check it again. - */ - mtx_assert(&Giant, MA_NOTOWNED); - mtx_lock_spin(&sched_lock); - if (!ithd->it_need) { - ithd->it_proc->p_stat = SWAIT; /* we're idle */ - CTR1(KTR_INTR, "ithd_loop pid %d: done", - ithd->it_proc->p_pid); - mi_switch(); - CTR1(KTR_INTR, "ithd_loop pid %d: resumed", - ithd->it_proc->p_pid); - } - mtx_unlock_spin(&sched_lock); - } -} static void alpha_clock_interrupt(void *framep) diff --git a/sys/alpha/include/intr.h b/sys/alpha/include/intr.h index c34cc00..6ff2271 100644 --- a/sys/alpha/include/intr.h +++ b/sys/alpha/include/intr.h @@ -29,11 +29,10 @@ #ifndef _MACHINE_INTR_H_ #define _MACHINE_INTR_H_ -int alpha_setup_intr(const char *name, int vector, - driver_intr_t *handle, void *arg, int pri, int flags, - void **cookiep, volatile long *cntp, - void (*disable)(int), void (*enable)(int)); -int alpha_teardown_intr(void *cookie); -void alpha_dispatch_intr(void *frame, unsigned long vector); +int alpha_setup_intr(const char *name, int vector, driver_intr_t handler, + void *arg, enum intr_type flags, void **cookiep, + volatile long *cntp, void (*disable)(int), void (*enable)(int)); +int alpha_teardown_intr(void *cookie); +void alpha_dispatch_intr(void *frame, unsigned long vector); #endif /* !_MACHINE_INTR_H_ */ diff --git a/sys/alpha/isa/isa.c b/sys/alpha/isa/isa.c index d22f8b0..48404b8 100644 --- a/sys/alpha/isa/isa.c +++ b/sys/alpha/isa/isa.c @@ -353,8 +353,7 @@ isa_setup_intr(device_t dev, device_t child, device_get_nameunit(child ? child : dev), 0x800 + (irq->r_start << 4), ((flags & INTR_FAST) ? isa_handle_fast_intr : - isa_handle_intr), ii, - ithread_priority(flags), flags, &ii->ih, + isa_handle_intr), ii, flags, &ii->ih, &intrcnt[INTRCNT_ISA_IRQ + irq->r_start], isa_disable_intr, isa_enable_intr); if (error) { diff --git a/sys/alpha/mcbus/mcpcia.c b/sys/alpha/mcbus/mcpcia.c index 7333bc2..03bb36e 100644 --- a/sys/alpha/mcbus/mcpcia.c +++ b/sys/alpha/mcbus/mcpcia.c @@ -345,7 +345,7 @@ mcpcia_setup_intr(device_t dev, device_t child, struct resource *ir, int flags, driver_intr_t *intr, void *arg, void **cp) { struct mcpcia_softc *sc = MCPCIA_SOFTC(dev); - int slot, mid, gid, birq, irq, error, intpin, h, pri; + int slot, mid, gid, birq, irq, error, intpin, h; intpin = pci_get_intpin(child); if (intpin == 0) { @@ -394,9 +394,8 @@ mcpcia_setup_intr(device_t dev, device_t child, struct resource *ir, int flags, ((intpin - 1) * MCPCIA_VECWIDTH_PER_INTPIN); } birq = irq + INTRCNT_KN300_IRQ; - pri = ithread_priority(flags); error = alpha_setup_intr(device_get_nameunit(child ? child : dev), h, - intr, arg, pri, flags, cp, &intrcnt[birq], + intr, arg, flags, cp, &intrcnt[birq], mcpcia_disable_intr_vec, mcpcia_enable_intr_vec); if (error) return error; diff --git a/sys/alpha/pci/apecs.c b/sys/alpha/pci/apecs.c index 8721e33..d67f7db 100644 --- a/sys/alpha/pci/apecs.c +++ b/sys/alpha/pci/apecs.c @@ -370,8 +370,7 @@ apecs_setup_intr(device_t dev, device_t child, return error; error = alpha_setup_intr(device_get_nameunit(child ? child : dev), - 0x900 + (irq->r_start << 4), intr, arg, - ithread_priority(flags), flags, cookiep, + 0x900 + (irq->r_start << 4), intr, arg, flags, cookiep, &intrcnt[INTRCNT_EB64PLUS_IRQ + irq->r_start], apecs_disable_intr, apecs_enable_intr); if (error) diff --git a/sys/alpha/pci/cia.c b/sys/alpha/pci/cia.c index 1bd9196..b7b8eb7 100644 --- a/sys/alpha/pci/cia.c +++ b/sys/alpha/pci/cia.c @@ -542,8 +542,7 @@ cia_setup_intr(device_t dev, device_t child, error = alpha_setup_intr( device_get_nameunit(child ? child : dev), - 0x900 + (irq->r_start << 4), intr, arg, - ithread_priority(flags), flags, cookiep, + 0x900 + (irq->r_start << 4), intr, arg, flags, cookiep, &intrcnt[INTRCNT_EB164_IRQ + irq->r_start], cia_disable_intr, cia_enable_intr); if (error) diff --git a/sys/alpha/pci/t2.c b/sys/alpha/pci/t2.c index 0e3c2a0..e0fe4ac 100644 --- a/sys/alpha/pci/t2.c +++ b/sys/alpha/pci/t2.c @@ -666,9 +666,8 @@ t2_setup_intr(device_t dev, device_t child, return error; error = alpha_setup_intr(device_get_nameunit(child ? child : dev), - vector, intr, arg, ithread_priority(flags), flags, - cookiep, &intrcnt[irq->r_start], - t2_disable_vec, t2_enable_vec); + vector, intr, arg, flags, cookiep, + &intrcnt[irq->r_start], t2_disable_vec, t2_enable_vec); if (error) return error; diff --git a/sys/alpha/pci/tsunami.c b/sys/alpha/pci/tsunami.c index c07200a..2e67cb9 100644 --- a/sys/alpha/pci/tsunami.c +++ b/sys/alpha/pci/tsunami.c @@ -330,8 +330,7 @@ tsunami_setup_intr(device_t dev, device_t child, return error; error = alpha_setup_intr(device_get_nameunit(child ? child : dev), - 0x900 + (irq->r_start << 4), intr, arg, - ithread_priority(flags), flags, cookiep, + 0x900 + (irq->r_start << 4), intr, arg, flags, cookiep, &intrcnt[INTRCNT_EB164_IRQ + irq->r_start], tsunami_disable_intr_vec, tsunami_enable_intr_vec); if (error) diff --git a/sys/alpha/tlsb/dwlpx.c b/sys/alpha/tlsb/dwlpx.c index 2e16a11..e9b621e 100644 --- a/sys/alpha/tlsb/dwlpx.c +++ b/sys/alpha/tlsb/dwlpx.c @@ -379,7 +379,7 @@ dwlpx_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_intr_t *intr, void *arg, void **cookiep) { struct dwlpx_softc *sc = DWLPX_SOFTC(dev); - int slot, ionode, hose, error, vector, intpin, pri; + int slot, ionode, hose, error, vector, intpin; error = rman_activate_resource(irq); if (error) @@ -391,9 +391,8 @@ dwlpx_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, hose = sc->bushose & 0x3; vector = DWLPX_MVEC(ionode, hose, slot); - pri = ithread_priority(flags); error = alpha_setup_intr(device_get_nameunit(child ? child : dev), - vector, intr, arg, pri, flags, cookiep, + vector, intr, arg, flags, cookiep, &intrcnt[INTRCNT_KN8AE_IRQ], NULL, NULL); if (error) return error; |