summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-10-01 20:19:20 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-10-01 20:19:20 +0000
commit2f170aacf72c46c917cdfe67ac32e89d65edf81d (patch)
tree1dc5956ddab9243ed357fece1a6b970c972f9953 /sys
parent6c8d318a056e70f92a487ab483553d455ad77e55 (diff)
Generic soft interrupts for macppc. Tested by mk@, deraadt@
ok miod@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/macppc/dev/macintr.c22
-rw-r--r--sys/arch/macppc/dev/openpic.c36
-rw-r--r--sys/arch/macppc/dev/zs.c17
-rw-r--r--sys/arch/macppc/include/z8530var.h13
-rw-r--r--sys/arch/macppc/macppc/autoconf.c6
-rw-r--r--sys/arch/macppc/macppc/clock.c4
-rw-r--r--sys/arch/macppc/macppc/machdep.c35
-rw-r--r--sys/arch/powerpc/conf/files.powerpc3
-rw-r--r--sys/arch/powerpc/include/_types.h3
-rw-r--r--sys/arch/powerpc/include/intr.h68
-rw-r--r--sys/arch/powerpc/powerpc/softintr.c221
-rw-r--r--sys/arch/socppc/dev/ipic.c10
-rw-r--r--sys/arch/socppc/socppc/autoconf.c4
-rw-r--r--sys/arch/socppc/socppc/clock.c4
-rw-r--r--sys/arch/socppc/socppc/machdep.c43
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;