Module Name: src Committed By: matt Date: Fri Jun 17 05:15:23 UTC 2011
Modified Files: src/sys/arch/powerpc/include: intr.h src/sys/arch/powerpc/pic: intr.c picvar.h Log Message: Change from level to ipl since we aren't dealing a mask anymore, just a simple value. Fix intr_calculatemasks to deal with ipl isn't a mask. Let establish and disestablish determine the highest ipl for the interrut source being modified. No reason to recompute that for every source when only one changes at a time. Only change idepth while in the loop. To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/powerpc/include/intr.h cvs rdiff -u -r1.13 -r1.14 src/sys/arch/powerpc/pic/intr.c cvs rdiff -u -r1.7 -r1.8 src/sys/arch/powerpc/pic/picvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/powerpc/include/intr.h diff -u src/sys/arch/powerpc/include/intr.h:1.6 src/sys/arch/powerpc/include/intr.h:1.7 --- src/sys/arch/powerpc/include/intr.h:1.6 Thu Jun 16 02:43:42 2011 +++ src/sys/arch/powerpc/include/intr.h Fri Jun 17 05:15:22 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: intr.h,v 1.6 2011/06/16 02:43:42 macallan Exp $ */ +/* $NetBSD: intr.h,v 1.7 2011/06/17 05:15:22 matt Exp $ */ /*- * Copyright (c) 2007 Michael Lorenz @@ -28,7 +28,7 @@ #ifndef _LOCORE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: intr.h,v 1.6 2011/06/16 02:43:42 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: intr.h,v 1.7 2011/06/17 05:15:22 matt Exp $"); #endif #ifndef POWERPC_INTR_MACHDEP_H @@ -73,7 +73,7 @@ int (*ih_fun)(void *); void *ih_arg; struct intrhand *ih_next; - int ih_level; + int ih_ipl; int ih_irq; }; Index: src/sys/arch/powerpc/pic/intr.c diff -u src/sys/arch/powerpc/pic/intr.c:1.13 src/sys/arch/powerpc/pic/intr.c:1.14 --- src/sys/arch/powerpc/pic/intr.c:1.13 Thu Jun 16 04:37:48 2011 +++ src/sys/arch/powerpc/pic/intr.c Fri Jun 17 05:15:23 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: intr.c,v 1.13 2011/06/16 04:37:48 matt Exp $ */ +/* $NetBSD: intr.c,v 1.14 2011/06/17 05:15:23 matt Exp $ */ /*- * Copyright (c) 2007 Michael Lorenz @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.13 2011/06/16 04:37:48 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.14 2011/06/17 05:15:23 matt Exp $"); #include "opt_multiprocessor.h" @@ -75,9 +75,7 @@ void pic_init(void) { - int i; - - for (i = 0; i < NIRQ; i++) + for (u_int i = 0; i < NIRQ; i++) virq[i] = 0; memset(intrsources, 0, sizeof(intrsources)); } @@ -113,18 +111,12 @@ static struct pic_ops * find_pic_by_irq(int irq) { - struct pic_ops *current; - int base = 0; - - while (base < num_pics) { - - current = pics[base]; - if ((irq >= current->pic_intrbase) && - (irq < (current->pic_intrbase + current->pic_numintrs))) { - - return current; + for (u_int base = 0; base < num_pics; base++) { + struct pic_ops * const pic = pics[base]; + if (pic->pic_intrbase <= irq + && irq < pic->pic_intrbase + pic->pic_numintrs) { + return pic; } - base++; } return NULL; } @@ -140,17 +132,17 @@ * Register an interrupt handler. */ void * -intr_establish(int hwirq, int type, int level, int (*ih_fun)(void *), +intr_establish(int hwirq, int type, int ipl, int (*ih_fun)(void *), void *ih_arg) { struct intrhand **p, *q, *ih; struct intr_source *is; struct pic_ops *pic; static struct intrhand fakehand; - int irq, maxlevel = level; + int irq, maxipl = ipl; - if (maxlevel == IPL_NONE) - maxlevel = IPL_HIGH; + if (maxipl == IPL_NONE) + maxipl = IPL_HIGH; if (hwirq >= max_base) { @@ -204,8 +196,7 @@ * generally small. */ for (p = &is->is_hand; (q = *p) != NULL; p = &q->ih_next) { - - maxlevel = max(maxlevel, q->ih_level); + maxipl = max(maxipl, q->ih_ipl); } /* @@ -213,7 +204,7 @@ * this with interrupts enabled and don't want the real routine called * until masking is set up. */ - fakehand.ih_level = level; + fakehand.ih_ipl = ipl; fakehand.ih_fun = fakeintr; *p = &fakehand; @@ -223,13 +214,18 @@ ih->ih_fun = ih_fun; ih->ih_arg = ih_arg; ih->ih_next = NULL; - ih->ih_level = level; + ih->ih_ipl = ipl; ih->ih_irq = irq; *p = ih; if (pic->pic_establish_irq != NULL) pic->pic_establish_irq(pic, hwirq - pic->pic_intrbase, - is->is_type, maxlevel); + is->is_type, maxipl); + + /* + * Remember the highest IPL used by this handler. + */ + is->is_ipl = maxipl; /* * now that the handler is established we're actually ready to @@ -252,10 +248,11 @@ void intr_disestablish(void *arg) { - struct intrhand *ih = arg; - int irq = ih->ih_irq; - struct intr_source *is = &intrsources[irq]; - struct intrhand **p, *q; + struct intrhand * const ih = arg; + const int irq = ih->ih_irq; + struct intr_source * const is = &intrsources[irq]; + struct intrhand **p, **q; + int maxipl = IPL_NONE; if (!LEGAL_VIRQ(irq)) panic("intr_disestablish: bogus irq %d", irq); @@ -264,14 +261,25 @@ * Remove the handler from the chain. * This is O(n^2), too. */ - for (p = &is->is_hand; (q = *p) != NULL && q != ih; p = &q->ih_next) - ; + for (p = &is->is_hand, q = NULL; (*p) != NULL; p = &(*p)->ih_next) { + struct intrhand * const tmp_ih = *p; + if (tmp_ih == ih) { + q = p; + } else { + maxipl = max(maxipl, tmp_ih->ih_ipl); + } + } if (q) - *p = q->ih_next; + *q = ih->ih_next; else panic("intr_disestablish: handler not registered"); free((void *)ih, M_DEVBUF); + /* + * Reset the IPL for this source now that we've removed a handler. + */ + is->is_ipl = maxipl; + intr_calculatemasks(); if (is->is_hand == NULL) { @@ -336,88 +344,59 @@ static void intr_calculatemasks(void) { + imask_t newmask[NIPL] = { [IPL_NONE...IPL_HIGH] = 0 }; struct intr_source *is; - struct intrhand *q; - struct pic_ops *current; - int irq, level, i, base; + int irq; - /* First, figure out which levels each IRQ uses. */ - for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) { - register int levels = 0; - for (q = is->is_hand; q; q = q->ih_next) - levels |= 1 << q->ih_level; - is->is_level = levels; + for (u_int ipl = IPL_NONE; ipl < NIPL; ipl++) { + newmask[ipl] = 0; } - /* Then figure out which IRQs use each level. */ - for (level = 0; level < NIPL; level++) { - register imask_t irqs = 0; - for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) - if (is->is_level & (1 << level)) - irqs |= 1ULL << irq; - imask[level] = irqs; + /* First, figure out which ipl each IRQ uses. */ + for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) { + newmask[is->is_ipl] |= 1ULL << irq; } /* * IPL_NONE is used for hardware interrupts that are never blocked, * and do not block anything else. */ - imask[IPL_NONE] = 0; + newmask[IPL_NONE] = 0; -#ifdef SLOPPY_IPLS - /* - * Enforce a sloppy hierarchy as in spl(9) - */ - /* everything above softclock must block softclock */ - for (i = IPL_SOFTCLOCK; i < NIPL; i++) - imask[i] |= imask[IPL_SOFTCLOCK]; - - /* everything above softnet must block softnet */ - for (i = IPL_SOFTNET; i < NIPL; i++) - imask[i] |= imask[IPL_SOFTNET]; - - /* IPL_TTY must block softserial */ - imask[IPL_TTY] |= imask[IPL_SOFTSERIAL]; - - /* IPL_VM must block net, block IO and tty */ - imask[IPL_VM] |= (imask[IPL_NET] | imask[IPL_BIO] | imask[IPL_TTY]); - - /* IPL_SERIAL must block IPL_TTY */ - imask[IPL_SERIAL] |= imask[IPL_TTY]; - - /* IPL_HIGH must block all other priority levels */ - for (i = IPL_NONE; i < IPL_HIGH; i++) - imask[IPL_HIGH] |= imask[i]; -#else /* !SLOPPY_IPLS */ /* * strict hierarchy - all IPLs block everything blocked by any lower * IPL */ - for (i = 1; i < NIPL; i++) - imask[i] |= imask[i - 1]; -#endif /* !SLOPPY_IPLS */ + for (u_int ipl = 1; ipl < NIPL; ipl++) { + newmask[ipl] |= newmask[ipl - 1]; + } #ifdef DEBUG_IPL - for (i = 0; i < NIPL; i++) { - printf("%2d: %08x\n", i, imask[i]); + for (u_int ipl = 0; ipl < NIPL; ipl++) { + printf("%u: %08x -> %08x\n", ipl, imask[ipl], newmask[ipl]); } #endif - /* And eventually calculate the complete masks. */ - for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) { - register imask_t irqs = 1ULL << irq; - for (q = is->is_hand; q; q = q->ih_next) - irqs |= imask[q->ih_level]; - is->is_mask = irqs; + /* + * Disable all interrupts. + */ + for (u_int base = 0; base < num_pics; base++) { + struct pic_ops * const pic = pics[base]; + for (u_int i = 0; i < pic->pic_numintrs; i++) { + pic->pic_disable_irq(pic, i); + } } - /* Lastly, enable IRQs actually in use. */ - for (base = 0; base < num_pics; base++) { - current = pics[base]; - for (i = 0; i < current->pic_numintrs; i++) - current->pic_disable_irq(current, i); + /* + * Now that all interrupts are disabled, update the ipl masks. + */ + for (u_int ipl = 0; ipl < NIPL; ipl++) { + imask[ipl] = newmask[ipl]; } + /* + * Lastly, enable IRQs actually in use. + */ for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) { if (is->is_hand) pic_enable_irq(is->is_hwirq); @@ -482,8 +461,8 @@ #endif /* Do now unmasked pendings */ - ci->ci_idepth++; while ((hwpend = (ci->ci_ipending & ~imask[pcpl] & HWIRQ_MASK)) != 0) { + ci->ci_idepth++; /* Get most significant pending bit */ irq = MS_PENDING(hwpend); KASSERT(irq <= virq_max); @@ -495,7 +474,7 @@ is = &intrsources[irq]; pic = is->is_pic; - splraise(is->is_level); + splraise(is->is_ipl); mtmsr(emsr); ih = is->is_hand; while (ih) { @@ -506,11 +485,11 @@ irq, is->is_hwirq, is); } #endif - if (ih->ih_level == IPL_VM) { + if (ih->ih_ipl == IPL_VM) { KERNEL_LOCK(1, NULL); } (*ih->ih_fun)(ih->ih_arg); - if (ih->ih_level == IPL_VM) { + if (ih->ih_ipl == IPL_VM) { KERNEL_UNLOCK_ONE(NULL); } ih = ih->ih_next; @@ -521,8 +500,8 @@ is->is_ev.ev_count++; pic->pic_reenable_irq(pic, is->is_hwirq - pic->pic_intrbase, is->is_type); + ci->ci_idepth--; } - ci->ci_idepth--; #ifdef __HAVE_FAST_SOFTINTS #if 0 @@ -626,7 +605,7 @@ ci->ci_ipending &= ~r_imen; ci->ci_idepth++; - splraise(is->is_level); + splraise(is->is_ipl); mtmsr(msr | PSL_EE); ih = is->is_hand; bail = 0; @@ -634,11 +613,11 @@ if (ih->ih_fun == NULL) panic("bogus handler for IRQ %s %d", pic->pic_name, realirq); - if (ih->ih_level == IPL_VM) { + if (ih->ih_ipl == IPL_VM) { KERNEL_LOCK(1, NULL); } (*ih->ih_fun)(ih->ih_arg); - if (ih->ih_level == IPL_VM) { + if (ih->ih_ipl == IPL_VM) { KERNEL_UNLOCK_ONE(NULL); } ih = ih->ih_next; Index: src/sys/arch/powerpc/pic/picvar.h diff -u src/sys/arch/powerpc/pic/picvar.h:1.7 src/sys/arch/powerpc/pic/picvar.h:1.8 --- src/sys/arch/powerpc/pic/picvar.h:1.7 Sat Apr 24 09:39:57 2010 +++ src/sys/arch/powerpc/pic/picvar.h Fri Jun 17 05:15:23 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: picvar.h,v 1.7 2010/04/24 09:39:57 kiyohara Exp $ */ +/* $NetBSD: picvar.h,v 1.8 2011/06/17 05:15:23 matt Exp $ */ /*- * Copyright (c) 2007 Michael Lorenz @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: picvar.h,v 1.7 2010/04/24 09:39:57 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: picvar.h,v 1.8 2011/06/17 05:15:23 matt Exp $"); #ifndef PIC_VAR_H #define PIC_VAR_H @@ -56,7 +56,7 @@ struct intr_source { int is_type; - int is_level; + int is_ipl; int is_hwirq; imask_t is_mask; struct intrhand *is_hand;