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;