diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-10-01 20:19:20 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-10-01 20:19:20 +0000 |
commit | 2f170aacf72c46c917cdfe67ac32e89d65edf81d (patch) | |
tree | 1dc5956ddab9243ed357fece1a6b970c972f9953 /sys | |
parent | 6c8d318a056e70f92a487ab483553d455ad77e55 (diff) |
Generic soft interrupts for macppc. Tested by mk@, deraadt@
ok miod@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/macppc/dev/macintr.c | 22 | ||||
-rw-r--r-- | sys/arch/macppc/dev/openpic.c | 36 | ||||
-rw-r--r-- | sys/arch/macppc/dev/zs.c | 17 | ||||
-rw-r--r-- | sys/arch/macppc/include/z8530var.h | 13 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/autoconf.c | 6 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/clock.c | 4 | ||||
-rw-r--r-- | sys/arch/macppc/macppc/machdep.c | 35 | ||||
-rw-r--r-- | sys/arch/powerpc/conf/files.powerpc | 3 | ||||
-rw-r--r-- | sys/arch/powerpc/include/_types.h | 3 | ||||
-rw-r--r-- | sys/arch/powerpc/include/intr.h | 68 | ||||
-rw-r--r-- | sys/arch/powerpc/powerpc/softintr.c | 221 | ||||
-rw-r--r-- | sys/arch/socppc/dev/ipic.c | 10 | ||||
-rw-r--r-- | sys/arch/socppc/socppc/autoconf.c | 4 | ||||
-rw-r--r-- | sys/arch/socppc/socppc/clock.c | 4 | ||||
-rw-r--r-- | sys/arch/socppc/socppc/machdep.c | 43 |
15 files changed, 340 insertions, 149 deletions
diff --git a/sys/arch/macppc/dev/macintr.c b/sys/arch/macppc/dev/macintr.c index f0f38b0a962..c73e45c0d9b 100644 --- a/sys/arch/macppc/dev/macintr.c +++ b/sys/arch/macppc/dev/macintr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: macintr.c,v 1.38 2009/08/22 02:54:50 mk Exp $ */ +/* $OpenBSD: macintr.c,v 1.39 2009/10/01 20:19:18 kettenis Exp $ */ /*- * Copyright (c) 1995 Per Fogelstrom @@ -374,7 +374,7 @@ intr_calculatemasks() for (irq = 0; irq < ICU_LEN; irq++) if (m_intrlevel[irq] & (1 << level)) irqs |= 1 << irq; - imask[level] = irqs | SINT_MASK; + imask[level] = irqs | SINT_ALLMASK; } /* @@ -387,7 +387,7 @@ intr_calculatemasks() imask[IPL_NET] |= imask[IPL_BIO]; imask[IPL_TTY] |= imask[IPL_NET]; imask[IPL_VM] |= imask[IPL_TTY]; - imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCK; + imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCKMASK; /* * These are pseudo-levels. @@ -400,7 +400,7 @@ intr_calculatemasks() register int irqs = 1 << irq; for (q = m_intrhand[irq]; q; q = q->ih_next) irqs |= imask[q->ih_level]; - m_intrmask[irq] = irqs | SINT_MASK; + m_intrmask[irq] = irqs | SINT_ALLMASK; } /* Lastly, determine which IRQs are actually in use. */ @@ -579,23 +579,17 @@ mac_intr_do_pending_int() do { if((ci->ci_ipending & SINT_CLOCK) & ~pcpl) { ci->ci_ipending &= ~SINT_CLOCK; - softclock(); + softintr_dispatch(SI_SOFTCLOCK); } if((ci->ci_ipending & SINT_NET) & ~pcpl) { - extern int netisr; - int pisr; - ci->ci_ipending &= ~SINT_NET; - while ((pisr = netisr) != 0) { - atomic_clearbits_int(&netisr, pisr); - softnet(pisr); - } + softintr_dispatch(SI_SOFTNET); } if((ci->ci_ipending & SINT_TTY) & ~pcpl) { ci->ci_ipending &= ~SINT_TTY; - softtty(); + softintr_dispatch(SI_SOFTTTY); } - } while ((ci->ci_ipending & SINT_MASK) & ~pcpl); + } while ((ci->ci_ipending & SINT_ALLMASK) & ~pcpl); ci->ci_ipending &= pcpl; ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */ ppc_intr_enable(s); diff --git a/sys/arch/macppc/dev/openpic.c b/sys/arch/macppc/dev/openpic.c index ca863b97c3e..2fc2070031c 100644 --- a/sys/arch/macppc/dev/openpic.c +++ b/sys/arch/macppc/dev/openpic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: openpic.c,v 1.57 2009/09/15 21:02:24 kettenis Exp $ */ +/* $OpenBSD: openpic.c,v 1.58 2009/10/01 20:19:18 kettenis Exp $ */ /*- * Copyright (c) 1995 Per Fogelstrom @@ -71,8 +71,8 @@ static int mapirq(int irq); int openpic_prog_button(void *arg); void openpic_enable_irq_mask(int irq_mask); -#define HWIRQ_MAX 27 -#define HWIRQ_MASK 0x0fffffff +#define HWIRQ_MAX (31 - (SI_NQUEUES + 1)) +#define HWIRQ_MASK (0xffffffff >> (SI_NQUEUES + 1)) /* IRQ vector used for inter-processor interrupts. */ #define IPI_VECTOR_NOP 64 @@ -414,9 +414,9 @@ openpic_calc_mask() for (i = IPL_NONE; i <= IPL_HIGH; i++) { if (i > IPL_NONE) - imask[i] |= SINT_MASK; + imask[i] |= SINT_ALLMASK; if (i >= IPL_CLOCK) - imask[i] |= SPL_CLOCK; + imask[i] |= SPL_CLOCKMASK; } imask[IPL_HIGH] = 0xffffffff; } @@ -492,7 +492,7 @@ openpic_do_pending_int() if (pripending == 0) continue; irq = 31 - cntlzw(pripending); - ci->ci_ipending &= ~(1L << irq); + ci->ci_ipending &= ~(1 << irq); ci->ci_cpl = imask[o_intrmaxlvl[o_hwirq[irq]]]; openpic_enable_irq_mask(~ci->ci_cpl); ih = o_intrhand[irq]; @@ -512,7 +512,7 @@ openpic_do_pending_int() hwpend = ci->ci_ipending & ~pcpl;/* Catch new pendings */ hwpend &= HWIRQ_MASK; } - ci->ci_cpl = pcpl | SINT_MASK; + ci->ci_cpl = pcpl | SINT_ALLMASK; openpic_enable_irq_mask(~ci->ci_cpl); atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_HARD); @@ -537,25 +537,19 @@ openpic_do_pending_softint(int pcpl) ci->ci_cpl = SINT_CLOCK|SINT_NET|SINT_TTY; ppc_intr_enable(1); KERNEL_LOCK(); - softclock(); + softintr_dispatch(SI_SOFTCLOCK); KERNEL_UNLOCK(); ppc_intr_disable(); continue; } if((ci->ci_ipending & SINT_NET) & ~pcpl) { - extern int netisr; - int pisr; - ci->ci_ipending &= ~SINT_NET; ci->ci_cpl = SINT_NET|SINT_TTY; - while ((pisr = netisr) != 0) { - atomic_clearbits_int(&netisr, pisr); - ppc_intr_enable(1); - KERNEL_LOCK(); - softnet(pisr); - KERNEL_UNLOCK(); - ppc_intr_disable(); - } + ppc_intr_enable(1); + KERNEL_LOCK(); + softintr_dispatch(SI_SOFTNET); + KERNEL_UNLOCK(); + ppc_intr_disable(); continue; } if((ci->ci_ipending & SINT_TTY) & ~pcpl) { @@ -563,12 +557,12 @@ openpic_do_pending_softint(int pcpl) ci->ci_cpl = SINT_TTY; ppc_intr_enable(1); KERNEL_LOCK(); - softtty(); + softintr_dispatch(SI_SOFTTTY); KERNEL_UNLOCK(); ppc_intr_disable(); continue; } - } while ((ci->ci_ipending & SINT_MASK) & ~pcpl); + } while ((ci->ci_ipending & SINT_ALLMASK) & ~pcpl); ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */ atomic_clearbits_int(&ci->ci_iactive, CI_IACTIVE_PROCESSING_SOFT); diff --git a/sys/arch/macppc/dev/zs.c b/sys/arch/macppc/dev/zs.c index 317992a7e22..0cfbb93f9f3 100644 --- a/sys/arch/macppc/dev/zs.c +++ b/sys/arch/macppc/dev/zs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: zs.c,v 1.17 2008/08/19 07:59:19 kettenis Exp $ */ +/* $OpenBSD: zs.c,v 1.18 2009/10/01 20:19:18 kettenis Exp $ */ /* $NetBSD: zs.c,v 1.17 2001/06/19 13:42:15 wiz Exp $ */ /* @@ -170,7 +170,7 @@ struct cfattach zsc_ca = { extern struct cfdriver zsc_cd; int zshard(void *); -int zssoft(void *); +void zssoft(void *); #ifdef ZS_TXDMA int zs_txdma_int(void *); #endif @@ -393,6 +393,9 @@ zsc_attach(struct device *parent, struct device *self, void *aux) mac_intr_establish(parent, intr[1][1], IST_LEVEL, IPL_TTY, zs_txdma_int, (void *)1, "zsdma1"); #endif + zsc->zsc_softintr = softintr_establish(IPL_SOFTTTY, zssoft, zsc); + if (zsc->zsc_softintr == NULL) + panic("zsattach: could not establish soft interrupt"); /* * Set the master interrupt enable and interrupt vector. @@ -476,8 +479,7 @@ zshard(void *arg) /* We are at splzs here, so no need to lock. */ if (zssoftpending == 0) { zssoftpending = 1; - /* XXX setsoftserial(); */ - setsofttty(); /* UGLY HACK!!! */ + softintr_schedule(zsc->zsc_softintr); } } } @@ -487,7 +489,7 @@ zshard(void *arg) /* * Similar scheme as for zshard (look at all of them) */ -int +void zssoft(arg) void *arg; { @@ -496,7 +498,7 @@ zssoft(arg) /* This is not the only ISR on this IPL. */ if (zssoftpending == 0) - return (0); + return; /* * The soft intr. bit will be set by zshard only if @@ -510,7 +512,6 @@ zssoft(arg) continue; (void) zsc_intr_soft(zsc); } - return (1); } #ifdef ZS_TXDMA @@ -534,7 +535,7 @@ zs_txdma_int(arg) if (cs->cs_softreq) { if (zssoftpending == 0) { zssoftpending = 1; - setsoftserial(); + softintr_schedule(zsc->zsc_softintr); } } return 1; diff --git a/sys/arch/macppc/include/z8530var.h b/sys/arch/macppc/include/z8530var.h index d40606c739d..f778e7e56e9 100644 --- a/sys/arch/macppc/include/z8530var.h +++ b/sys/arch/macppc/include/z8530var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: z8530var.h,v 1.7 2008/06/13 00:31:09 krw Exp $ */ +/* $OpenBSD: z8530var.h,v 1.8 2009/10/01 20:19:18 kettenis Exp $ */ /* $NetBSD: z8530var.h,v 1.5 2002/03/17 19:40:45 atatat Exp $ */ /* @@ -92,12 +92,13 @@ struct xzs_chanstate { }; struct zsc_softc { - struct device zsc_dev; /* required first: base device */ - struct zs_chanstate *zsc_cs[2]; /* channel A and B soft state */ + struct device zsc_dev; /* base device */ + struct zs_chanstate *zsc_cs[2]; /* channel A and B soft state */ /* Machine-dependent part follows... */ - struct xzs_chanstate xzsc_xcs_store[2]; - dbdma_regmap_t *zsc_txdmareg[2]; - dbdma_command_t *zsc_txdmacmd[2]; + void *zsc_softintr; + struct xzs_chanstate xzsc_xcs_store[2]; + dbdma_regmap_t *zsc_txdmareg[2]; + dbdma_command_t *zsc_txdmacmd[2]; /* XXX tx only, for now */ }; diff --git a/sys/arch/macppc/macppc/autoconf.c b/sys/arch/macppc/macppc/autoconf.c index c5fff86d81a..cd083d973bb 100644 --- a/sys/arch/macppc/macppc/autoconf.c +++ b/sys/arch/macppc/macppc/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.37 2009/08/29 11:41:32 miod Exp $ */ +/* $OpenBSD: autoconf.c,v 1.38 2009/10/01 20:19:18 kettenis Exp $ */ /* * Copyright (c) 1996, 1997 Per Fogelstrom * Copyright (c) 1995 Theo de Raadt @@ -37,7 +37,7 @@ * from: Utah Hdr: autoconf.c 1.31 91/01/21 * * from: @(#)autoconf.c 8.1 (Berkeley) 6/10/93 - * $Id: autoconf.c,v 1.37 2009/08/29 11:41:32 miod Exp $ + * $Id: autoconf.c,v 1.38 2009/10/01 20:19:18 kettenis Exp $ */ /* @@ -93,6 +93,8 @@ cpu_configure() (void)splhigh(); /* To be really sure.. */ calc_delayconst(); + softintr_init(); + if (config_rootfound("mainbus", "mainbus") == 0) panic("no mainbus found"); (void)spl0(); diff --git a/sys/arch/macppc/macppc/clock.c b/sys/arch/macppc/macppc/clock.c index c0dc55a3d3d..bab7bca11f6 100644 --- a/sys/arch/macppc/macppc/clock.c +++ b/sys/arch/macppc/macppc/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.29 2009/06/09 01:12:38 deraadt Exp $ */ +/* $OpenBSD: clock.c,v 1.30 2009/10/01 20:19:18 kettenis Exp $ */ /* $NetBSD: clock.c,v 1.1 1996/09/30 16:34:40 ws Exp $ */ /* @@ -225,7 +225,7 @@ decr_intr(struct clockframe *frame) */ ppc_mtdec(nextevent - tb); - if (ci->ci_cpl & SPL_CLOCK) { + if (ci->ci_cpl & SPL_CLOCKMASK) { ci->ci_statspending += nstats; } else { KERNEL_LOCK(); diff --git a/sys/arch/macppc/macppc/machdep.c b/sys/arch/macppc/macppc/machdep.c index fb070245b49..1350c9ed053 100644 --- a/sys/arch/macppc/macppc/machdep.c +++ b/sys/arch/macppc/macppc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.114 2009/08/22 02:54:50 mk Exp $ */ +/* $OpenBSD: machdep.c,v 1.115 2009/10/01 20:19:19 kettenis Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -54,8 +54,6 @@ #include <uvm/uvm_extern.h> -#include <net/netisr.h> - #include <dev/cons.h> #include <machine/bat.h> @@ -830,37 +828,6 @@ dumpsys() int imask[IPL_NUM]; -/* - * this is a hack interface to allow zs to work better until - * a true soft interrupt mechanism is created. - */ -#include "zstty.h" -#if NZSTTY > 0 - extern void zssoft(void *); -#endif -void -softtty() -{ -#if NZSTTY > 0 - zssoft(0); -#endif -} - -int netisr; - -/* - * Soft networking interrupts. - */ -void -softnet(int isr) -{ -#define DONETISR(flag, func) \ - if (isr & (1 << flag))\ - func(); - -#include <net/netisr_dispatch.h> -} - int lcsplx(int ipl) { diff --git a/sys/arch/powerpc/conf/files.powerpc b/sys/arch/powerpc/conf/files.powerpc index 51c7956b2a8..6710564694a 100644 --- a/sys/arch/powerpc/conf/files.powerpc +++ b/sys/arch/powerpc/conf/files.powerpc @@ -1,4 +1,4 @@ -# $OpenBSD: files.powerpc,v 1.46 2008/04/25 14:51:35 jmc Exp $ +# $OpenBSD: files.powerpc,v 1.47 2009/10/01 20:19:19 kettenis Exp $ # file arch/powerpc/powerpc/setjmp.S ddb @@ -14,6 +14,7 @@ file arch/powerpc/powerpc/trap.c file arch/powerpc/powerpc/vm_machdep.c file arch/powerpc/powerpc/mutex.S file arch/powerpc/powerpc/intr.c +file arch/powerpc/powerpc/softintr.c file arch/powerpc/ddb/db_memrw.c ddb file arch/powerpc/ddb/db_disasm.c ddb diff --git a/sys/arch/powerpc/include/_types.h b/sys/arch/powerpc/include/_types.h index 9d3a51f6e95..9cf552e0b4f 100644 --- a/sys/arch/powerpc/include/_types.h +++ b/sys/arch/powerpc/include/_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: _types.h,v 1.8 2008/07/21 20:50:55 martynas Exp $ */ +/* $OpenBSD: _types.h,v 1.9 2009/10/01 20:19:19 kettenis Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -118,6 +118,7 @@ typedef void * __wctrans_t; typedef void * __wctype_t; /* Feature test macros */ +#define __HAVE_GENERIC_SOFT_INTERRUPTS #define __HAVE_TIMECOUNTER #endif /* _POWERPC__TYPES_H_ */ diff --git a/sys/arch/powerpc/include/intr.h b/sys/arch/powerpc/include/intr.h index 455cebf38dd..937c3f5f26e 100644 --- a/sys/arch/powerpc/include/intr.h +++ b/sys/arch/powerpc/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.42 2009/08/22 02:54:50 mk Exp $ */ +/* $OpenBSD: intr.h,v 1.43 2009/10/01 20:19:19 kettenis Exp $ */ /* * Copyright (c) 1997 Per Fogelstrom, Opsycon AB and RTMX Inc, USA. @@ -59,13 +59,6 @@ #define PPC_CLK_IRQ 64 #define PPC_STAT_IRQ 65 -void setsoftclock(void); -void clearsoftclock(void); -int splsoftclock(void); -void setsoftnet(void); -void clearsoftnet(void); -int splsoftnet(void); - int splraise(int); int spllower(int); void splx(int); @@ -79,13 +72,56 @@ extern int imask[IPL_NUM]; #define splassert(wantipl) /* nothing */ #define splsoftassert(wantipl) /* nothing */ -#define set_sint(p) atomic_setbits_int(&curcpu()->ci_ipending, p) +#define SINTBIT(q) (31 - (q)) +#define SINTMASK(q) (1 << SINTBIT(q)) + +#define SPL_CLOCKMASK SINTMASK(SI_NQUEUES) + +/* Soft interrupt masks. */ + +#define IPL_SOFTCLOCK 0 +#define IPL_SOFTNET 1 +#define IPL_SOFTTTY 2 -#define SINT_CLOCK 0x10000000 -#define SINT_NET 0x20000000 -#define SINT_TTY 0x40000000 -#define SPL_CLOCK 0x80000000 -#define SINT_MASK (SINT_CLOCK|SINT_NET|SINT_TTY) +#define SI_SOFTCLOCK 0 /* for IPL_SOFTCLOCK */ +#define SI_SOFTNET 1 /* for IPL_SOFTNET */ +#define SI_SOFTTTY 2 /* for IPL_SOFTTY */ + +#define SINT_ALLMASK (SINTMASK(SI_SOFTCLOCK) | \ + SINTMASK(SI_SOFTNET) | SINTMASK(SI_SOFTTTY)) +#define SI_NQUEUES 3 + +#include <machine/mutex.h> +#include <sys/queue.h> + +struct soft_intrhand { + TAILQ_ENTRY(soft_intrhand) sih_list; + void (*sih_func)(void *); + void *sih_arg; + struct soft_intrq *sih_siq; + int sih_pending; +}; + +struct soft_intrq { + TAILQ_HEAD(, soft_intrhand) siq_list; + int siq_si; + struct mutex siq_mtx; +}; + +void softintr_disestablish(void *); +void softintr_dispatch(int); +void *softintr_establish(int, void (*)(void *), void *); +void softintr_init(void); +void softintr_schedule(void *); + +/* XXX For legacy software interrupts. */ +extern struct soft_intrhand *softnet_intrhand; + +#define setsoftnet() softintr_schedule(softnet_intrhand) + +#define SINT_CLOCK SINTMASK(SI_SOFTCLOCK) +#define SINT_NET SINTMASK(SI_SOFTNET) +#define SINT_TTY SINTMASK(SI_SOFTTTY) #define splbio() splraise(imask[IPL_BIO]) #define splnet() splraise(imask[IPL_NET]) @@ -100,10 +136,6 @@ extern int imask[IPL_NUM]; #define splsoftnet() splraise(SINT_NET|SINT_CLOCK) #define splsofttty() splraise(SINT_TTY|SINT_NET|SINT_CLOCK) -#define setsoftclock() set_sint(SINT_CLOCK); -#define setsoftnet() set_sint(SINT_NET); -#define setsofttty() set_sint(SINT_TTY); - #define splhigh() splraise(0xffffffff) #define spl0() spllower(0) diff --git a/sys/arch/powerpc/powerpc/softintr.c b/sys/arch/powerpc/powerpc/softintr.c new file mode 100644 index 00000000000..79ddc5cd627 --- /dev/null +++ b/sys/arch/powerpc/powerpc/softintr.c @@ -0,0 +1,221 @@ +/* $OpenBSD: softintr.c,v 1.1 2009/10/01 20:19:19 kettenis Exp $ */ +/* $NetBSD: softintr.c,v 1.2 2003/07/15 00:24:39 lukem Exp $ */ + +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/malloc.h> + +/* XXX Network interrupts should be converted to new softintrs. */ +#include <net/netisr.h> + +#include <uvm/uvm_extern.h> + +#include <machine/atomic.h> +#include <machine/intr.h> + +struct soft_intrq soft_intrq[SI_NQUEUES]; + +struct soft_intrhand *softnet_intrhand; + +void netintr(void); + +/* + * Initialize the software interrupt system. + */ +void +softintr_init(void) +{ + struct soft_intrq *siq; + int i; + + for (i = 0; i < SI_NQUEUES; i++) { + siq = &soft_intrq[i]; + TAILQ_INIT(&siq->siq_list); + siq->siq_si = i; + mtx_init(&siq->siq_mtx, IPL_HIGH); + } + + /* XXX Establish legacy software interrupt handlers. */ + softnet_intrhand = softintr_establish(IPL_SOFTNET, + (void (*)(void *))netintr, NULL); +} + +/* + * Process pending software interrupts on the specified queue. + * + * NOTE: We must already be at the correct interrupt priority level. + */ +void +softintr_dispatch(int si) +{ + struct soft_intrq *siq = &soft_intrq[si]; + struct soft_intrhand *sih; + + for (;;) { + mtx_enter(&siq->siq_mtx); + sih = TAILQ_FIRST(&siq->siq_list); + if (sih == NULL) { + mtx_leave(&siq->siq_mtx); + break; + } + + TAILQ_REMOVE(&siq->siq_list, sih, sih_list); + sih->sih_pending = 0; + + uvmexp.softs++; + + mtx_leave(&siq->siq_mtx); + + (*sih->sih_func)(sih->sih_arg); + } +} + +/* + * Register a software interrupt handler. + */ +void * +softintr_establish(int ipl, void (*func)(void *), void *arg) +{ + struct soft_intrhand *sih; + int si; + + switch (ipl) { +#if 0 + case IPL_SOFT: + si = SI_SOFT; + break; +#endif + case IPL_SOFTCLOCK: + si = SI_SOFTCLOCK; + break; + case IPL_SOFTNET: + si = SI_SOFTNET; + break; + case IPL_TTY: /* XXX until MI code is fixed */ + case IPL_SOFTTTY: + si = SI_SOFTTTY; + break; + default: + printf("softintr_establish: unknown soft IPL %d\n", ipl); + return NULL; + } + + sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT); + if (__predict_true(sih != NULL)) { + sih->sih_func = func; + sih->sih_arg = arg; + sih->sih_siq = &soft_intrq[si]; + sih->sih_pending = 0; + } + return (sih); +} + +/* + * Unregister a software interrupt handler. + */ +void +softintr_disestablish(void *arg) +{ + struct soft_intrhand *sih = arg; + struct soft_intrq *siq = sih->sih_siq; + + mtx_enter(&siq->siq_mtx); + if (sih->sih_pending) { + TAILQ_REMOVE(&siq->siq_list, sih, sih_list); + sih->sih_pending = 0; + } + mtx_leave(&siq->siq_mtx); + + free(sih, M_DEVBUF); +} + +/* + * Schedule a software interrupt. + */ +void +softintr_schedule(void *arg) +{ + struct soft_intrhand *sih = (struct soft_intrhand *)arg; + struct soft_intrq *siq = sih->sih_siq; + struct cpu_info *ci = curcpu(); + + mtx_enter(&siq->siq_mtx); + if (sih->sih_pending == 0) { + TAILQ_INSERT_TAIL(&siq->siq_list, sih, sih_list); + sih->sih_pending = 1; + atomic_setbits_int(&ci->ci_ipending, SINTMASK(siq->siq_si)); + } + mtx_leave(&siq->siq_mtx); +} + +int netisr; + +void +netintr(void) +{ + int n; + + while ((n = netisr) != 0) { + atomic_clearbits_int(&netisr, n); +#define DONETISR(bit, fn) \ + do { \ + if (n & (1 << (bit))) \ + fn(); \ + } while (0) +#include <net/netisr_dispatch.h> +#undef DONETISR + } +} + +#if 0 +void +dosoftint(int xcpl) +{ + struct cpu_info *ci = curcpu(); + int sir, q, mask; + + while ((sir = (ci->ci_ipending & SINT_ALLMASK & ~xcpl)) != 0) { + atomic_clearbits_int(&ci->ci_ipending, sir); + + for (q = SI_NQUEUES - 1; q >= 0; q--) { + mask = SINTMASK(q); + if (sir & mask) + softintr_dispatch(q); + } + } +} +#endif diff --git a/sys/arch/socppc/dev/ipic.c b/sys/arch/socppc/dev/ipic.c index 5b0b59bfac6..3d51da16528 100644 --- a/sys/arch/socppc/dev/ipic.c +++ b/sys/arch/socppc/dev/ipic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipic.c,v 1.10 2009/09/12 21:38:01 kettenis Exp $ */ +/* $OpenBSD: ipic.c,v 1.11 2009/10/01 20:19:19 kettenis Exp $ */ /* * Copyright (c) 2008 Mark Kettenis @@ -221,7 +221,7 @@ intr_calculatemasks(void) int level; for (level = IPL_NONE; level < IPL_NUM; level++) - imask[level] = SINT_MASK | (1 << level); + imask[level] = SINT_ALLMASK | (1 << level); /* * There are tty, network and disk drivers that use free() at interrupt @@ -233,7 +233,7 @@ intr_calculatemasks(void) imask[IPL_NET] |= imask[IPL_BIO]; imask[IPL_TTY] |= imask[IPL_NET]; imask[IPL_VM] |= imask[IPL_TTY]; - imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCK; + imask[IPL_CLOCK] |= imask[IPL_VM] | SPL_CLOCKMASK; /* * These are pseudo-levels. @@ -376,8 +376,8 @@ ipic_do_pending_int(void) uint32_t mask; int level; - ci->ci_ipending &= SINT_MASK; - level = cntlzw(31 - (ci->ci_cpl & ~(SPL_CLOCK|SINT_MASK))); + ci->ci_ipending &= SINT_ALLMASK; + level = cntlzw(31 - (ci->ci_cpl & ~(SPL_CLOCKMASK|SINT_ALLMASK))); mask = sc->sc_simsr_h[IPL_HIGH] & ~sc->sc_simsr_h[level]; ipic_write(sc, IPIC_SIMSR_H, mask); mask = sc->sc_simsr_l[IPL_HIGH] & ~sc->sc_simsr_l[level]; diff --git a/sys/arch/socppc/socppc/autoconf.c b/sys/arch/socppc/socppc/autoconf.c index e1fdcc53264..bd0c90758e1 100644 --- a/sys/arch/socppc/socppc/autoconf.c +++ b/sys/arch/socppc/socppc/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.3 2008/07/21 04:35:54 todd Exp $ */ +/* $OpenBSD: autoconf.c,v 1.4 2009/10/01 20:19:19 kettenis Exp $ */ /* * Copyright (c) 2008 Mark Kettenis @@ -36,6 +36,8 @@ cpu_configure(void) { splhigh(); + softintr_init(); + if (config_rootfound("mainbus", "mainbus") == 0) panic("no mainbus found"); diff --git a/sys/arch/socppc/socppc/clock.c b/sys/arch/socppc/socppc/clock.c index 4b335b7e20d..4a3d87d3fb5 100644 --- a/sys/arch/socppc/socppc/clock.c +++ b/sys/arch/socppc/socppc/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.6 2009/09/07 21:52:17 kettenis Exp $ */ +/* $OpenBSD: clock.c,v 1.7 2009/10/01 20:19:19 kettenis Exp $ */ /* $NetBSD: clock.c,v 1.1 1996/09/30 16:34:40 ws Exp $ */ /* @@ -202,7 +202,7 @@ decr_intr(struct clockframe *frame) */ ppc_mtdec(nextevent - tb); - if (curcpu()->ci_cpl & SPL_CLOCK) { + if (curcpu()->ci_cpl & SPL_CLOCKMASK) { ci->ci_statspending += nstats; } else { KERNEL_LOCK(); diff --git a/sys/arch/socppc/socppc/machdep.c b/sys/arch/socppc/socppc/machdep.c index 6c8f7afc552..2c22254ad7a 100644 --- a/sys/arch/socppc/socppc/machdep.c +++ b/sys/arch/socppc/socppc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.22 2009/08/30 14:57:41 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.23 2009/10/01 20:19:19 kettenis Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -57,8 +57,6 @@ #include <machine/powerpc.h> #include <machine/trap.h> -#include <net/netisr.h> - #include <dev/cons.h> #include <dev/ic/comvar.h> @@ -477,21 +475,6 @@ dumpsys(void) int imask[IPL_NUM]; -int netisr; - -/* - * Soft networking interrupts. - */ -void -softnet(int isr) -{ -#define DONETISR(flag, func) \ - if (isr & (1 << flag))\ - func(); - -#include <net/netisr_dispatch.h> -} - int lcsplx(int ipl) { @@ -1138,40 +1121,32 @@ do_pending_int(void) ci->ci_cpl = SINT_CLOCK|SINT_NET|SINT_TTY; ppc_intr_enable(1); KERNEL_LOCK(); - softclock(); + softintr_dispatch(SI_SOFTCLOCK); KERNEL_UNLOCK(); ppc_intr_disable(); continue; } if((ci->ci_ipending & SINT_NET) & ~pcpl) { - extern int netisr; - int pisr; - ci->ci_ipending &= ~SINT_NET; ci->ci_cpl = SINT_NET|SINT_TTY; - while ((pisr = netisr) != 0) { - atomic_clearbits_int(&netisr, pisr); - ppc_intr_enable(1); - KERNEL_LOCK(); - softnet(pisr); - KERNEL_UNLOCK(); - ppc_intr_disable(); - } + ppc_intr_enable(1); + KERNEL_LOCK(); + softintr_dispatch(SI_SOFTNET); + KERNEL_UNLOCK(); + ppc_intr_disable(); continue; } -#if 0 if((ci->ci_ipending & SINT_TTY) & ~pcpl) { ci->ci_ipending &= ~SINT_TTY; ci->ci_cpl = SINT_TTY; ppc_intr_enable(1); KERNEL_LOCK(); - softtty(); + softintr_dispatch(SI_SOFTTTY); KERNEL_UNLOCK(); ppc_intr_disable(); continue; } -#endif - } while ((ci->ci_ipending & SINT_MASK) & ~pcpl); + } while ((ci->ci_ipending & SINT_ALLMASK) & ~pcpl); ci->ci_cpl = pcpl; /* Don't use splx... we are here already! */ ci->ci_iactive = 0; |