Module Name: src Committed By: thorpej Date: Fri Sep 25 03:40:12 UTC 2020
Modified Files: src/sys/arch/alpha/alpha: interrupt.c src/sys/arch/alpha/common: shared_intr.c src/sys/arch/alpha/include: cpu.h intr.h types.h src/sys/arch/alpha/jensenio: com_jensenio.c jensenio_intr.c jenseniovar.h pckbc_jensenio.c src/sys/arch/alpha/pci: dwlpx.c pci_2100_a500.c pci_kn300.c pci_kn8ae.c pci_machdep.c sio_pic.c src/sys/arch/alpha/tc: tc_3000_300.c tc_3000_500.c tcasic.c Log Message: Changes to make interrupt {,dis}establish MP-safe on Alpha: - Protect all of the system interrupt linkage with the cpu_lock mutex. - Re-order some of the stores to the SCB vector table to make it safe in the face of lockless interrupt dispatch. - Add a framework for routing interrupts to specific CPUs. Interrupts are still funneled only to the primary CPU, but that will change for some systems soon. Ensure that interrupt handler lists are manipulated only on the CPUs that handle that specific interrupt source. This required a re-factor of the alpha_shared_intr_*() family of functions. - Enable __HAVE_INTR_CONTROL, although interrupt redistribution is still a no-op. - Reduce code duplication in the Jenson direct-SCB interrupt handlers. To generate a diff of this commit: cvs rdiff -u -r1.89 -r1.90 src/sys/arch/alpha/alpha/interrupt.c cvs rdiff -u -r1.24 -r1.25 src/sys/arch/alpha/common/shared_intr.c cvs rdiff -u -r1.96 -r1.97 src/sys/arch/alpha/include/cpu.h cvs rdiff -u -r1.80 -r1.81 src/sys/arch/alpha/include/intr.h cvs rdiff -u -r1.59 -r1.60 src/sys/arch/alpha/include/types.h cvs rdiff -u -r1.17 -r1.18 src/sys/arch/alpha/jensenio/com_jensenio.c cvs rdiff -u -r1.12 -r1.13 src/sys/arch/alpha/jensenio/jensenio_intr.c cvs rdiff -u -r1.4 -r1.5 src/sys/arch/alpha/jensenio/jenseniovar.h cvs rdiff -u -r1.13 -r1.14 src/sys/arch/alpha/jensenio/pckbc_jensenio.c cvs rdiff -u -r1.38 -r1.39 src/sys/arch/alpha/pci/dwlpx.c cvs rdiff -u -r1.13 -r1.14 src/sys/arch/alpha/pci/pci_2100_a500.c cvs rdiff -u -r1.37 -r1.38 src/sys/arch/alpha/pci/pci_kn300.c cvs rdiff -u -r1.30 -r1.31 src/sys/arch/alpha/pci/pci_kn8ae.c cvs rdiff -u -r1.25 -r1.26 src/sys/arch/alpha/pci/pci_machdep.c cvs rdiff -u -r1.44 -r1.45 src/sys/arch/alpha/pci/sio_pic.c cvs rdiff -u -r1.36 -r1.37 src/sys/arch/alpha/tc/tc_3000_300.c cvs rdiff -u -r1.35 -r1.36 src/sys/arch/alpha/tc/tc_3000_500.c cvs rdiff -u -r1.48 -r1.49 src/sys/arch/alpha/tc/tcasic.c 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/alpha/alpha/interrupt.c diff -u src/sys/arch/alpha/alpha/interrupt.c:1.89 src/sys/arch/alpha/alpha/interrupt.c:1.90 --- src/sys/arch/alpha/alpha/interrupt.c:1.89 Tue Sep 22 15:24:01 2020 +++ src/sys/arch/alpha/alpha/interrupt.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: interrupt.c,v 1.89 2020/09/22 15:24:01 thorpej Exp $ */ +/* $NetBSD: interrupt.c,v 1.90 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -65,7 +65,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: interrupt.c,v 1.89 2020/09/22 15:24:01 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: interrupt.c,v 1.90 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -88,11 +88,10 @@ __KERNEL_RCSID(0, "$NetBSD: interrupt.c, #include <machine/cpuconf.h> #include <machine/alpha.h> +/* Protected by cpu_lock */ struct scbvec scb_iovectab[SCB_VECTOIDX(SCB_SIZE - SCB_IOVECBASE)] __read_mostly; -void netintr(void); - void scb_stray(void *, u_long); void @@ -117,9 +116,8 @@ void scb_set(u_long vec, void (*func)(void *, u_long), void *arg) { u_long idx; - int s; - s = splhigh(); + KASSERT(mutex_owned(&cpu_lock)); if (vec < SCB_IOVECBASE || vec >= SCB_SIZE || (vec & (SCB_VECSIZE - 1)) != 0) @@ -130,19 +128,18 @@ scb_set(u_long vec, void (*func)(void *, if (scb_iovectab[idx].scb_func != scb_stray) panic("scb_set: vector 0x%lx already occupied", vec); - scb_iovectab[idx].scb_func = func; scb_iovectab[idx].scb_arg = arg; - - splx(s); + alpha_mb(); + scb_iovectab[idx].scb_func = func; + alpha_mb(); } u_long scb_alloc(void (*func)(void *, u_long), void *arg) { u_long vec, idx; - int s; - s = splhigh(); + KASSERT(mutex_owned(&cpu_lock)); /* * Allocate "downwards", to avoid bumping into @@ -153,15 +150,14 @@ scb_alloc(void (*func)(void *, u_long), vec >= SCB_IOVECBASE; vec -= SCB_VECSIZE) { idx = SCB_VECTOIDX(vec - SCB_IOVECBASE); if (scb_iovectab[idx].scb_func == scb_stray) { - scb_iovectab[idx].scb_func = func; scb_iovectab[idx].scb_arg = arg; - splx(s); + alpha_mb(); + scb_iovectab[idx].scb_func = func; + alpha_mb(); return (vec); } } - splx(s); - return (SCB_ALLOC_FAILED); } @@ -169,9 +165,8 @@ void scb_free(u_long vec) { u_long idx; - int s; - s = splhigh(); + KASSERT(mutex_owned(&cpu_lock)); if (vec < SCB_IOVECBASE || vec >= SCB_SIZE || (vec & (SCB_VECSIZE - 1)) != 0) @@ -183,9 +178,9 @@ scb_free(u_long vec) panic("scb_free: vector 0x%lx is empty", vec); scb_iovectab[idx].scb_func = scb_stray; + alpha_mb(); scb_iovectab[idx].scb_arg = (void *) vec; - - splx(s); + alpha_mb(); } void @@ -581,6 +576,28 @@ cpu_intr_p(void) } /* + * cpu_intr_redistribute: + * + * Redistribute interrupts amongst CPUs eligible to handle them. + */ +void +cpu_intr_redistribute(void) +{ + /* XXX Nothing, yet. */ +} + +/* + * cpu_intr_count: + * + * Return the number of device interrupts this CPU handles. + */ +unsigned int +cpu_intr_count(struct cpu_info * const ci) +{ + return ci->ci_nintrhand; +} + +/* * Security sensitive rate limiting printf */ void Index: src/sys/arch/alpha/common/shared_intr.c diff -u src/sys/arch/alpha/common/shared_intr.c:1.24 src/sys/arch/alpha/common/shared_intr.c:1.25 --- src/sys/arch/alpha/common/shared_intr.c:1.24 Wed Sep 23 18:46:02 2020 +++ src/sys/arch/alpha/common/shared_intr.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,33 @@ -/* $NetBSD: shared_intr.c,v 1.24 2020/09/23 18:46:02 thorpej Exp $ */ +/* $NetBSD: shared_intr.c,v 1.25 2020/09/25 03:40:11 thorpej Exp $ */ + +/* + * Copyright (c) 2020 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 THE FOUNDATION OR CONTRIBUTORS + * 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. + */ /* * Copyright (c) 1996 Carnegie-Mellon University. @@ -33,16 +62,19 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: shared_intr.c,v 1.24 2020/09/23 18:46:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: shared_intr.c,v 1.25 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/param.h> #include <sys/kernel.h> +#include <sys/cpu.h> +#include <sys/kmem.h> +#include <sys/kmem.h> #include <sys/systm.h> -#include <sys/malloc.h> #include <sys/syslog.h> #include <sys/queue.h> #include <sys/atomic.h> #include <sys/intr.h> +#include <sys/xcall.h> static const char *intr_typename(int); @@ -71,8 +103,7 @@ alpha_shared_intr_alloc(unsigned int n, struct alpha_shared_intr *intr; unsigned int i; - intr = malloc(n * sizeof (struct alpha_shared_intr), M_DEVBUF, - M_WAITOK); + intr = kmem_alloc(n * sizeof(*intr), KM_SLEEP); for (i = 0; i < n; i++) { TAILQ_INIT(&intr[i].intr_q); intr[i].intr_sharetype = IST_NONE; @@ -80,11 +111,12 @@ alpha_shared_intr_alloc(unsigned int n, intr[i].intr_nstrays = 0; intr[i].intr_maxstrays = 5; intr[i].intr_private = NULL; + intr[i].intr_cpu = NULL; if (namesize != 0) { - intr[i].intr_string = malloc(namesize, M_DEVBUF, - M_WAITOK); - } else + intr[i].intr_string = kmem_zalloc(namesize, KM_SLEEP); + } else { intr[i].intr_string = NULL; + } } return (intr); @@ -132,24 +164,82 @@ alpha_shared_intr_wrapper(void * const a return rv; } -void * -alpha_shared_intr_establish(struct alpha_shared_intr *intr, unsigned int num, - int type, int level, int flags, +struct alpha_shared_intrhand * +alpha_shared_intr_alloc_intrhand(struct alpha_shared_intr *intr, + unsigned int num, int type, int level, int flags, int (*fn)(void *), void *arg, const char *basename) { struct alpha_shared_intrhand *ih; if (intr[num].intr_sharetype == IST_UNUSABLE) { - printf("alpha_shared_intr_establish: %s %d: unusable\n", + printf("%s: %s %d: unusable\n", __func__, basename, num); return NULL; } - ih = malloc(sizeof *ih, M_DEVBUF, M_WAITOK); -#ifdef DIAGNOSTIC - if (type == IST_NONE) - panic("alpha_shared_intr_establish: bogus type"); -#endif + KASSERT(type != IST_NONE); + + ih = kmem_alloc(sizeof(*ih), KM_SLEEP); + + ih->ih_intrhead = intr; + ih->ih_fn = ih->ih_real_fn = fn; + ih->ih_arg = ih->ih_real_arg = arg; + ih->ih_level = level; + ih->ih_type = type; + ih->ih_num = num; + + /* + * Non-MPSAFE interrupts get a wrapper that takes the + * KERNEL_LOCK. + */ + if ((flags & ALPHA_INTR_MPSAFE) == 0) { + ih->ih_fn = alpha_shared_intr_wrapper; + ih->ih_arg = ih; + } + + return (ih); +} + +void +alpha_shared_intr_free_intrhand(struct alpha_shared_intrhand *ih) +{ + + kmem_free(ih, sizeof(*ih)); +} + +static void +alpha_shared_intr_link_unlink_xcall(void *arg1, void *arg2) +{ + struct alpha_shared_intrhand *ih = arg1; + struct alpha_shared_intr *intr = ih->ih_intrhead; + struct cpu_info *ci = intr->intr_cpu; + unsigned int num = ih->ih_num; + + KASSERT(ci == curcpu() || !mp_online); + KASSERT(!cpu_intr_p()); + + const unsigned long psl = alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); + + if (arg2 != NULL) { + TAILQ_INSERT_TAIL(&intr[num].intr_q, ih, ih_q); + ci->ci_nintrhand++; + } else { + TAILQ_REMOVE(&intr[num].intr_q, ih, ih_q); + ci->ci_nintrhand--; + } + + alpha_pal_swpipl(psl); +} + +bool +alpha_shared_intr_link(struct alpha_shared_intr *intr, + struct alpha_shared_intrhand *ih, const char *basename) +{ + int type = ih->ih_type; + unsigned int num = ih->ih_num; + + KASSERT(mutex_owned(&cpu_lock)); + KASSERT(ih->ih_intrhead == intr); switch (intr[num].intr_sharetype) { case IST_EDGE: @@ -164,9 +254,10 @@ alpha_shared_intr_establish(struct alpha intr_typename(intr[num].intr_sharetype)); type = intr[num].intr_sharetype; } else { - panic("alpha_shared_intr_establish: %s %d: can't share %s with %s", + printf("alpha_shared_intr_establish: %s %d: can't share %s with %s\n", basename, num, intr_typename(type), intr_typename(intr[num].intr_sharetype)); + return (false); } } break; @@ -176,39 +267,47 @@ alpha_shared_intr_establish(struct alpha break; } - ih->ih_intrhead = intr; - ih->ih_fn = ih->ih_real_fn = fn; - ih->ih_arg = ih->ih_real_arg = arg; - ih->ih_level = level; - ih->ih_num = num; + intr[num].intr_sharetype = type; /* - * Non-MPSAFE interrupts get a wrapper that takes the - * KERNEL_LOCK. + * If a CPU hasn't been assigned yet, just give it to the + * primary. */ - if ((flags & ALPHA_INTR_MPSAFE) == 0) { - ih->ih_fn = alpha_shared_intr_wrapper; - ih->ih_arg = ih; + if (intr->intr_cpu == NULL) { + intr->intr_cpu = &cpu_info_primary; } - intr[num].intr_sharetype = type; - TAILQ_INSERT_TAIL(&intr[num].intr_q, ih, ih_q); + kpreempt_disable(); + if (intr->intr_cpu == curcpu() || !mp_online) { + alpha_shared_intr_link_unlink_xcall(ih, intr); + } else { + uint64_t where = xc_unicast(XC_HIGHPRI, + alpha_shared_intr_link_unlink_xcall, ih, intr, + intr->intr_cpu); + xc_wait(where); + } + kpreempt_enable(); - return (ih); + return (true); } void -alpha_shared_intr_disestablish(struct alpha_shared_intr *intr, void *cookie, - const char *basename) +alpha_shared_intr_unlink(struct alpha_shared_intr *intr, + struct alpha_shared_intrhand *ih, const char *basename) { - struct alpha_shared_intrhand *ih = cookie; - unsigned int num = ih->ih_num; - /* - * Just remove it from the list and free the entry. We let - * the caller deal with resetting the share type, if appropriate. - */ - TAILQ_REMOVE(&intr[num].intr_q, ih, ih_q); + KASSERT(mutex_owned(&cpu_lock)); + + kpreempt_disable(); + if (intr->intr_cpu == curcpu() || !mp_online) { + alpha_shared_intr_link_unlink_xcall(ih, NULL); + } else { + uint64_t where = xc_unicast(XC_HIGHPRI, + alpha_shared_intr_link_unlink_xcall, ih, NULL, + intr->intr_cpu); + xc_wait(where); + } + kpreempt_enable(); } int @@ -302,6 +401,21 @@ alpha_shared_intr_get_private(struct alp return (intr[num].intr_private); } +void +alpha_shared_intr_set_cpu(struct alpha_shared_intr *intr, unsigned int num, + struct cpu_info *ci) +{ + + intr[num].intr_cpu = ci; +} + +struct cpu_info * +alpha_shared_intr_get_cpu(struct alpha_shared_intr *intr, unsigned int num) +{ + + return (intr[num].intr_cpu); +} + struct evcnt * alpha_shared_intr_evcnt(struct alpha_shared_intr *intr, unsigned int num) Index: src/sys/arch/alpha/include/cpu.h diff -u src/sys/arch/alpha/include/cpu.h:1.96 src/sys/arch/alpha/include/cpu.h:1.97 --- src/sys/arch/alpha/include/cpu.h:1.96 Wed Sep 16 04:07:32 2020 +++ src/sys/arch/alpha/include/cpu.h Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.96 2020/09/16 04:07:32 thorpej Exp $ */ +/* $NetBSD: cpu.h,v 1.97 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -139,6 +139,7 @@ struct cpu_info { volatile u_long ci_flags; /* flags; see below */ uint64_t ci_pcc_freq; /* cpu cycles/second */ struct trapframe *ci_db_regs; /* registers for debuggers */ + u_int ci_nintrhand; /* # of interrupt handlers */ }; /* Ensure some cpu_info fields are within the signed 16-bit displacement. */ Index: src/sys/arch/alpha/include/intr.h diff -u src/sys/arch/alpha/include/intr.h:1.80 src/sys/arch/alpha/include/intr.h:1.81 --- src/sys/arch/alpha/include/intr.h:1.80 Wed Sep 23 18:47:21 2020 +++ src/sys/arch/alpha/include/intr.h Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: intr.h,v 1.80 2020/09/23 18:47:21 thorpej Exp $ */ +/* $NetBSD: intr.h,v 1.81 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc. @@ -206,6 +206,7 @@ struct alpha_shared_intrhand { int (*ih_real_fn)(void *); void *ih_real_arg; int ih_level; + int ih_type; unsigned int ih_num; }; @@ -215,6 +216,7 @@ struct alpha_shared_intr { struct evcnt intr_evcnt; char *intr_string; void *intr_private; + struct cpu_info *intr_cpu; int intr_sharetype; int intr_dfltsharetype; int intr_nstrays; @@ -228,10 +230,15 @@ struct alpha_shared_intr { struct alpha_shared_intr *alpha_shared_intr_alloc(unsigned int, unsigned int); int alpha_shared_intr_dispatch(struct alpha_shared_intr *, unsigned int); -void *alpha_shared_intr_establish(struct alpha_shared_intr *, - unsigned int, int, int, int, int (*)(void *), void *, const char *); -void alpha_shared_intr_disestablish(struct alpha_shared_intr *, - void *, const char *); +struct alpha_shared_intrhand * + alpha_shared_intr_alloc_intrhand(struct alpha_shared_intr *, + unsigned int, int, int, int, int (*)(void *), void *, + const char *); +void alpha_shared_intr_free_intrhand(struct alpha_shared_intrhand *); +bool alpha_shared_intr_link(struct alpha_shared_intr *, + struct alpha_shared_intrhand *, const char *); +void alpha_shared_intr_unlink(struct alpha_shared_intr *, + struct alpha_shared_intrhand *, const char *); int alpha_shared_intr_get_sharetype(struct alpha_shared_intr *, unsigned int); int alpha_shared_intr_isactive(struct alpha_shared_intr *, @@ -250,6 +257,11 @@ void alpha_shared_intr_set_private(struc unsigned int, void *); void *alpha_shared_intr_get_private(struct alpha_shared_intr *, unsigned int); +void alpha_shared_intr_set_cpu(struct alpha_shared_intr *, + unsigned int, struct cpu_info *ci); +struct cpu_info * + alpha_shared_intr_get_cpu(struct alpha_shared_intr *, + unsigned int); char *alpha_shared_intr_string(struct alpha_shared_intr *, unsigned int); struct evcnt *alpha_shared_intr_evcnt(struct alpha_shared_intr *, Index: src/sys/arch/alpha/include/types.h diff -u src/sys/arch/alpha/include/types.h:1.59 src/sys/arch/alpha/include/types.h:1.60 --- src/sys/arch/alpha/include/types.h:1.59 Sat Sep 19 03:02:07 2020 +++ src/sys/arch/alpha/include/types.h Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: types.h,v 1.59 2020/09/19 03:02:07 thorpej Exp $ */ +/* $NetBSD: types.h,v 1.60 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -79,6 +79,7 @@ typedef __register_t register_t; #define __HAVE_MM_MD_DIRECT_MAPPED_PHYS #define __HAVE_CPU_DATA_FIRST #define __HAVE_FAST_SOFTINTS +#define __HAVE_INTR_CONTROL #define __HAVE_CPU_UAREA_ROUTINES #define __HAVE_CPU_LWP_SETPRIVATE #define __HAVE___LWP_GETPRIVATE_FAST Index: src/sys/arch/alpha/jensenio/com_jensenio.c diff -u src/sys/arch/alpha/jensenio/com_jensenio.c:1.17 src/sys/arch/alpha/jensenio/com_jensenio.c:1.18 --- src/sys/arch/alpha/jensenio/com_jensenio.c:1.17 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/jensenio/com_jensenio.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: com_jensenio.c,v 1.17 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: com_jensenio.c,v 1.18 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: com_jensenio.c,v 1.17 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: com_jensenio.c,v 1.18 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -46,6 +46,7 @@ __KERNEL_RCSID(0, "$NetBSD: com_jensenio #include <sys/syslog.h> #include <sys/types.h> #include <sys/device.h> +#include <sys/cpu.h> #include <machine/intr.h> #include <sys/bus.h> @@ -63,8 +64,7 @@ struct com_jensenio_softc { struct com_softc sc_com; /* real "com" softc */ /* Jensen-specific goo. */ - char sc_vecstr[8]; - struct evcnt sc_ev_intr; + struct jensenio_scb_intrhand sc_jih; }; int com_jensenio_match(device_t, cfdata_t , void *); @@ -73,8 +73,6 @@ void com_jensenio_attach(device_t, devic CFATTACH_DECL_NEW(com_jensenio, sizeof(struct com_jensenio_softc), com_jensenio_match, com_jensenio_attach, NULL, NULL); -void com_jensenio_intr(void *, u_long); - int com_jensenio_match(device_t parent, cfdata_t match, void *aux) { @@ -118,26 +116,13 @@ com_jensenio_attach(device_t parent, dev com_attach_subr(sc); - scb_set(ja->ja_irq[0], com_jensenio_intr, jsc); + jensenio_intr_establish(&jsc->sc_jih, ja->ja_irq[0], + 0, comintr, sc); + aprint_normal_dev(self, "interrupting at vector 0x%x\n", ja->ja_irq[0]); - snprintf(jsc->sc_vecstr, sizeof(jsc->sc_vecstr), "0x%x", ja->ja_irq[0]); - evcnt_attach_dynamic(&jsc->sc_ev_intr, EVCNT_TYPE_INTR, - NULL, "vector", jsc->sc_vecstr); - if (!pmf_device_register1(self, com_suspend, com_resume, com_cleanup)) { aprint_error_dev(self, "could not establish shutdown hook"); } } - -void -com_jensenio_intr(void *arg, u_long vec) -{ - struct com_jensenio_softc *jsc = arg; - - KERNEL_LOCK(1, NULL); - jsc->sc_ev_intr.ev_count++; - (void) comintr(&jsc->sc_com); - KERNEL_UNLOCK_ONE(NULL); -} Index: src/sys/arch/alpha/jensenio/jensenio_intr.c diff -u src/sys/arch/alpha/jensenio/jensenio_intr.c:1.12 src/sys/arch/alpha/jensenio/jensenio_intr.c:1.13 --- src/sys/arch/alpha/jensenio/jensenio_intr.c:1.12 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/jensenio/jensenio_intr.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: jensenio_intr.c,v 1.12 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: jensenio_intr.c,v 1.13 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: jensenio_intr.c,v 1.12 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: jensenio_intr.c,v 1.13 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -40,6 +40,7 @@ __KERNEL_RCSID(0, "$NetBSD: jensenio_int #include <sys/errno.h> #include <sys/malloc.h> #include <sys/device.h> +#include <sys/cpu.h> #include <sys/syslog.h> #include <machine/autoconf.h> @@ -158,6 +159,58 @@ jensenio_intr_init(struct jensenio_confi ic->ic_intr_evcnt = jensenio_eisa_intr_evcnt; } +static void +jensenio_intr_dispatch(void *arg, unsigned long vec) +{ + struct jensenio_scb_intrhand *jih = arg; + + jih->jih_evcnt.ev_count++; + (void) jih->jih_func(jih->jih_arg); +} + +static void +jensenio_intr_dispatch_wrapped(void *arg, unsigned long vec) +{ + KERNEL_LOCK(1, NULL); + jensenio_intr_dispatch(arg, vec); + KERNEL_UNLOCK_ONE(NULL); +} + +void +jensenio_intr_establish(struct jensenio_scb_intrhand *jih, + unsigned long vec, int flags, int (*func)(void *), void *arg) +{ + void (*scb_func)(void *, unsigned long); + + /* + * Jensen systems are all uniprocessors, but we still do all + * of the KERNEL_LOCK handling as a formality to keep assertions + * valid in MI code. + */ + KASSERT(CPU_IS_PRIMARY(curcpu())); + KASSERT(ncpu == 1); + if (flags & ALPHA_INTR_MPSAFE) + scb_func = jensenio_intr_dispatch; + else + scb_func = jensenio_intr_dispatch_wrapped; + + jih->jih_func = func; + jih->jih_arg = arg; + jih->jih_vec = vec; + + snprintf(jih->jih_vecstr, sizeof(jih->jih_vecstr), "0x%lx", + jih->jih_vec); + evcnt_attach_dynamic(&jih->jih_evcnt, EVCNT_TYPE_INTR, + NULL, "vector", jih->jih_vecstr); + + mutex_enter(&cpu_lock); + + scb_set(vec, scb_func, jih); + curcpu()->ci_nintrhand++; + + mutex_exit(&cpu_lock); +} + int jensenio_eisa_intr_map(void *v, u_int eirq, eisa_intr_handle_t *ihp) { @@ -211,14 +264,24 @@ jensenio_eisa_intr_establish(void *v, in if (jensenio_intr_deftype[irq] == IST_UNUSABLE) { printf("jensenio_eisa_intr_establish: IRQ %d not usable\n", irq); - return (NULL); + return NULL; } - cookie = alpha_shared_intr_establish(jensenio_eisa_intr, irq, + cookie = alpha_shared_intr_alloc_intrhand(jensenio_eisa_intr, irq, type, level, 0, fn, arg, "eisa irq"); - if (cookie != NULL && - alpha_shared_intr_firstactive(jensenio_eisa_intr, irq)) { + if (cookie == NULL) + return NULL; + + mutex_enter(&cpu_lock); + + if (! alpha_shared_intr_link(jensenio_eisa_intr, cookie, "eisa irq")) { + mutex_exit(&cpu_lock); + alpha_shared_intr_free_intrhand(cookie); + return NULL; + } + + if (alpha_shared_intr_firstactive(jensenio_eisa_intr, irq)) { scb_set(0x800 + SCB_IDXTOVEC(irq), jensenio_iointr, NULL); jensenio_setlevel(irq, alpha_shared_intr_get_sharetype(jensenio_eisa_intr, @@ -226,29 +289,31 @@ jensenio_eisa_intr_establish(void *v, in jensenio_enable_intr(irq, 1); } - return (cookie); + mutex_exit(&cpu_lock); + + return cookie; } void jensenio_eisa_intr_disestablish(void *v, void *cookie) { struct alpha_shared_intrhand *ih = cookie; - int s, irq = ih->ih_num; + int irq = ih->ih_num; - s = splhigh(); + mutex_enter(&cpu_lock); - /* Remove it from the link. */ - alpha_shared_intr_disestablish(jensenio_eisa_intr, cookie, - "eisa irq"); - - if (alpha_shared_intr_isactive(jensenio_eisa_intr, irq) == 0) { + if (alpha_shared_intr_firstactive(jensenio_eisa_intr, irq)) { jensenio_enable_intr(irq, 0); alpha_shared_intr_set_dfltsharetype(jensenio_eisa_intr, irq, jensenio_intr_deftype[irq]); scb_free(0x800 + SCB_IDXTOVEC(irq)); } - splx(s); + alpha_shared_intr_unlink(jensenio_eisa_intr, cookie, "eisa irq"); + + mutex_exit(&cpu_lock); + + alpha_shared_intr_free_intrhand(cookie); } int Index: src/sys/arch/alpha/jensenio/jenseniovar.h diff -u src/sys/arch/alpha/jensenio/jenseniovar.h:1.4 src/sys/arch/alpha/jensenio/jenseniovar.h:1.5 --- src/sys/arch/alpha/jensenio/jenseniovar.h:1.4 Mon Apr 28 20:23:11 2008 +++ src/sys/arch/alpha/jensenio/jenseniovar.h Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: jenseniovar.h,v 1.4 2008/04/28 20:23:11 martin Exp $ */ +/* $NetBSD: jenseniovar.h,v 1.5 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -32,6 +32,8 @@ #ifndef _ALPHA_JENSENIO_JENSENIOVAR_H_ #define _ALPHA_JENSENIO_JENSENIOVAR_H_ +#include <sys/evcnt.h> + /* * Arguments used to attach devices to the Jensen I/O bus. */ @@ -74,10 +76,25 @@ struct jensenio_config { int jc_mallocsafe; }; +/* + * Interrupt handle for Jensen I/O interrupts that hook into + * the SCB directly. + */ +struct jensenio_scb_intrhand { + int (*jih_func)(void *); + void *jih_arg; + unsigned long jih_vec; + char jih_vecstr[8]; + struct evcnt jih_evcnt; +}; + void jensenio_init(struct jensenio_config *, int); void jensenio_bus_io_init(bus_space_tag_t, void *); void jensenio_bus_intio_init(bus_space_tag_t, void *); void jensenio_bus_mem_init(bus_space_tag_t, void *); void jensenio_intr_init(struct jensenio_config *); void jensenio_dma_init(struct jensenio_config *); + +void jensenio_intr_establish(struct jensenio_scb_intrhand *, + unsigned long, int, int (*)(void *), void *); #endif /* _ALPHA_JENSENIO_JENSENIOVAR_H_ */ Index: src/sys/arch/alpha/jensenio/pckbc_jensenio.c diff -u src/sys/arch/alpha/jensenio/pckbc_jensenio.c:1.13 src/sys/arch/alpha/jensenio/pckbc_jensenio.c:1.14 --- src/sys/arch/alpha/jensenio/pckbc_jensenio.c:1.13 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/jensenio/pckbc_jensenio.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pckbc_jensenio.c,v 1.13 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: pckbc_jensenio.c,v 1.14 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: pckbc_jensenio.c,v 1.13 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pckbc_jensenio.c,v 1.14 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: pckbc_jensen #include <sys/queue.h> #include <sys/intr.h> #include <sys/bus.h> +#include <sys/cpu.h> #include <dev/ic/i8042reg.h> #include <dev/ic/pckbcvar.h> @@ -53,18 +54,11 @@ __KERNEL_RCSID(0, "$NetBSD: pckbc_jensen #include <alpha/jensenio/jenseniovar.h> -struct pckbc_jensenio_intrcookie { - struct pckbc_softc *ic_sc; - struct evcnt ic_ev; - u_long ic_vector; - char ic_vecstr[8]; -}; - struct pckbc_jensenio_softc { struct pckbc_softc sc_pckbc; /* real "pckbc" softc */ /* Jensen-specific goo. */ - struct pckbc_jensenio_intrcookie sc_ic[PCKBC_NSLOTS]; + struct jensenio_scb_intrhand sc_jih[PCKBC_NSLOTS]; }; int pckbc_jensenio_match(device_t, cfdata_t, void *); @@ -74,7 +68,6 @@ CFATTACH_DECL_NEW(pckbc_jensenio, sizeof pckbc_jensenio_match, pckbc_jensenio_attach, NULL, NULL); void pckbc_jensenio_intr_establish(struct pckbc_softc *, pckbc_slot_t); -void pckbc_jensenio_intr(void *, u_long); int pckbc_jensenio_match(device_t parent, cfdata_t match, void *aux) @@ -102,8 +95,8 @@ pckbc_jensenio_attach(device_t parent, d /* * Set up IRQs. */ - jsc->sc_ic[PCKBC_KBD_SLOT].ic_vector = ja->ja_irq[0]; - jsc->sc_ic[PCKBC_AUX_SLOT].ic_vector = ja->ja_irq[1]; + jsc->sc_jih[PCKBC_KBD_SLOT].jih_vec = ja->ja_irq[0]; + jsc->sc_jih[PCKBC_AUX_SLOT].jih_vec = ja->ja_irq[1]; sc->intr_establish = pckbc_jensenio_intr_establish; @@ -141,26 +134,9 @@ pckbc_jensenio_intr_establish(struct pck { struct pckbc_jensenio_softc *jsc = (void *) sc; - jsc->sc_ic[slot].ic_sc = sc; + jensenio_intr_establish(&jsc->sc_jih[slot], + jsc->sc_jih[slot].jih_vec, 0, pckbcintr, sc); - scb_set(jsc->sc_ic[slot].ic_vector, pckbc_jensenio_intr, - &jsc->sc_ic[slot]); aprint_normal_dev(sc->sc_dv, "%s slot interrupting at vector 0x%lx\n", - pckbc_slot_names[slot], jsc->sc_ic[slot].ic_vector); - - snprintf(jsc->sc_ic[slot].ic_vecstr, sizeof(jsc->sc_ic[slot].ic_vecstr), - "0x%lx", jsc->sc_ic[slot].ic_vector); - evcnt_attach_dynamic(&jsc->sc_ic[slot].ic_ev, EVCNT_TYPE_INTR, - NULL, "vector", jsc->sc_ic[slot].ic_vecstr); -} - -void -pckbc_jensenio_intr(void *arg, u_long vec) -{ - struct pckbc_jensenio_intrcookie *ic = arg; - - KERNEL_LOCK(1, NULL); - ic->ic_ev.ev_count++; - (void) pckbcintr(ic->ic_sc); - KERNEL_UNLOCK_ONE(NULL); + pckbc_slot_names[slot], jsc->sc_jih[slot].jih_vec); } Index: src/sys/arch/alpha/pci/dwlpx.c diff -u src/sys/arch/alpha/pci/dwlpx.c:1.38 src/sys/arch/alpha/pci/dwlpx.c:1.39 --- src/sys/arch/alpha/pci/dwlpx.c:1.38 Mon Feb 6 02:14:14 2012 +++ src/sys/arch/alpha/pci/dwlpx.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: dwlpx.c,v 1.38 2012/02/06 02:14:14 matt Exp $ */ +/* $NetBSD: dwlpx.c,v 1.39 2020/09/25 03:40:11 thorpej Exp $ */ /* * Copyright (c) 1997 by Matthew Jacob @@ -32,12 +32,13 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: dwlpx.c,v 1.38 2012/02/06 02:14:14 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dwlpx.c,v 1.39 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/device.h> +#include <sys/cpu.h> #include <machine/autoconf.h> @@ -251,7 +252,9 @@ dwlpx_init(struct dwlpx_softc *sc) * Do this even for all HPCs- even for the nonexistent * one on hose zero of a KFTIA. */ + mutex_enter(&cpu_lock); vec = scb_alloc(dwlpx_errintr, sc); + mutex_exit(&cpu_lock); if (vec == SCB_ALLOC_FAILED) panic("%s: unable to allocate error vector", device_xname(sc->dwlpx_dev)); Index: src/sys/arch/alpha/pci/pci_2100_a500.c diff -u src/sys/arch/alpha/pci/pci_2100_a500.c:1.13 src/sys/arch/alpha/pci/pci_2100_a500.c:1.14 --- src/sys/arch/alpha/pci/pci_2100_a500.c:1.13 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/pci/pci_2100_a500.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_2100_a500.c,v 1.13 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: pci_2100_a500.c,v 1.14 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: pci_2100_a500.c,v 1.13 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_2100_a500.c,v 1.14 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -40,6 +40,7 @@ __KERNEL_RCSID(0, "$NetBSD: pci_2100_a50 #include <sys/errno.h> #include <sys/malloc.h> #include <sys/device.h> +#include <sys/cpu.h> #include <sys/syslog.h> #include <machine/autoconf.h> @@ -432,17 +433,29 @@ dec_2100_a500_intr_establish(pci_chipset KASSERT(irq < SABLE_MAX_IRQ); - cookie = alpha_shared_intr_establish(pc->pc_shared_intrs, irq, + cookie = alpha_shared_intr_alloc_intrhand(pc->pc_shared_intrs, irq, dec_2100_a500_intr_deftype[irq], level, flags, func, arg, "T2 irq"); - if (cookie != NULL && - alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { + if (cookie == NULL) + return NULL; + + mutex_enter(&cpu_lock); + + if (! alpha_shared_intr_link(pc->pc_shared_intrs, cookie, "T2 irq")) { + mutex_exit(&cpu_lock); + alpha_shared_intr_free_intrhand(cookie); + return NULL; + } + + if (alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { scb_set(pc->pc_vecbase + SCB_IDXTOVEC(irq), dec_2100_a500_iointr, tcp); (*tcp->tc_enable_intr)(tcp, irq, 1); } - return (cookie); + mutex_exit(&cpu_lock); + + return cookie; } static void @@ -451,20 +464,21 @@ dec_2100_a500_intr_disestablish(pci_chip struct ttwoga_config *tcp = pc->pc_intr_v; struct alpha_shared_intrhand *ih = cookie; unsigned int irq = ih->ih_num; - int s; - s = splhigh(); + mutex_enter(&cpu_lock); - alpha_shared_intr_disestablish(pc->pc_shared_intrs, cookie, - "T2 irq"); - if (alpha_shared_intr_isactive(pc->pc_shared_intrs, irq) == 0) { + if (alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { (*tcp->tc_enable_intr)(tcp, irq, 0); alpha_shared_intr_set_dfltsharetype(pc->pc_shared_intrs, irq, dec_2100_a500_intr_deftype[irq]); scb_free(pc->pc_vecbase + SCB_IDXTOVEC(irq)); } - splx(s); + alpha_shared_intr_unlink(pc->pc_shared_intrs, cookie, "T2 irq"); + + mutex_exit(&cpu_lock); + + alpha_shared_intr_free_intrhand(cookie); } /***************************************************************************** @@ -554,11 +568,21 @@ dec_2100_a500_eisa_intr_establish(void * return (NULL); } - cookie = alpha_shared_intr_establish(pc->pc_shared_intrs, irq, + cookie = alpha_shared_intr_alloc_intrhand(pc->pc_shared_intrs, irq, type, level, 0, fn, arg, "T2 irq"); - if (cookie != NULL && - alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { + if (cookie == NULL) + return NULL; + + mutex_enter(&cpu_lock); + + if (! alpha_shared_intr_link(pc->pc_shared_intrs, cookie, "T2 irq")) { + mutex_exit(&cpu_lock); + alpha_shared_intr_free_intrhand(cookie); + return NULL; + } + + if (alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { scb_set(pc->pc_vecbase + SCB_IDXTOVEC(irq), dec_2100_a500_iointr, tcp); (*tcp->tc_setlevel)(tcp, eirq, @@ -567,7 +591,9 @@ dec_2100_a500_eisa_intr_establish(void * (*tcp->tc_enable_intr)(tcp, irq, 1); } - return (cookie); + mutex_exit(&cpu_lock); + + return cookie; } static void @@ -576,22 +602,23 @@ dec_2100_a500_eisa_intr_disestablish(voi struct ttwoga_config *tcp = v; pci_chipset_tag_t const pc = &tcp->tc_pc; struct alpha_shared_intrhand *ih = cookie; - int s, irq = ih->ih_num; - - s = splhigh(); + int irq = ih->ih_num; - /* Remove it from the link. */ - alpha_shared_intr_disestablish(pc->pc_shared_intrs, cookie, - "T2 irq"); + mutex_enter(&cpu_lock); - if (alpha_shared_intr_isactive(pc->pc_shared_intrs, irq) == 0) { + if (alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { (*tcp->tc_enable_intr)(tcp, irq, 0); alpha_shared_intr_set_dfltsharetype(pc->pc_shared_intrs, irq, dec_2100_a500_intr_deftype[irq]); scb_free(pc->pc_vecbase + SCB_IDXTOVEC(irq)); } - splx(s); + /* Remove it from the link. */ + alpha_shared_intr_unlink(pc->pc_shared_intrs, cookie, "T2 irq"); + + mutex_exit(&cpu_lock); + + alpha_shared_intr_free_intrhand(cookie); } static int Index: src/sys/arch/alpha/pci/pci_kn300.c diff -u src/sys/arch/alpha/pci/pci_kn300.c:1.37 src/sys/arch/alpha/pci/pci_kn300.c:1.38 --- src/sys/arch/alpha/pci/pci_kn300.c:1.37 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/pci/pci_kn300.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_kn300.c,v 1.37 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: pci_kn300.c,v 1.38 2020/09/25 03:40:11 thorpej Exp $ */ /* * Copyright (c) 1998 by Matthew Jacob @@ -32,7 +32,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: pci_kn300.c,v 1.37 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_kn300.c,v 1.38 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: pci_kn300.c, #include <sys/errno.h> #include <sys/malloc.h> #include <sys/device.h> +#include <sys/cpu.h> #include <sys/syslog.h> #include <machine/autoconf.h> @@ -213,18 +214,31 @@ dec_kn300_intr_establish( const u_int irq = ihv & 0x3ff; const u_int flags = alpha_pci_intr_handle_get_flags(&ih); - cookie = alpha_shared_intr_establish(kn300_pci_intr, irq, IST_LEVEL, - level, flags, func, arg, "kn300 irq"); + cookie = alpha_shared_intr_alloc_intrhand(kn300_pci_intr, irq, + IST_LEVEL, level, flags, func, arg, "kn300 irq"); - if (cookie != NULL && - alpha_shared_intr_firstactive(kn300_pci_intr, irq)) { + if (cookie == NULL) + return NULL; + + mutex_enter(&cpu_lock); + + if (! alpha_shared_intr_link(kn300_pci_intr, cookie, "kn300 irq")) { + mutex_exit(&cpu_lock); + alpha_shared_intr_free_intrhand(cookie); + return NULL; + } + + if (alpha_shared_intr_firstactive(kn300_pci_intr, irq)) { scb_set(MCPCIA_VEC_PCI + SCB_IDXTOVEC(irq), kn300_iointr, NULL); alpha_shared_intr_set_private(kn300_pci_intr, irq, ccp); savirqs[irq] = (ihv >> 11) & 0x1f; - kn300_enable_intr(ccp, savirqs[irq]); alpha_mb(); + kn300_enable_intr(ccp, savirqs[irq]); } - return (cookie); + + mutex_exit(&cpu_lock); + + return cookie; } static void Index: src/sys/arch/alpha/pci/pci_kn8ae.c diff -u src/sys/arch/alpha/pci/pci_kn8ae.c:1.30 src/sys/arch/alpha/pci/pci_kn8ae.c:1.31 --- src/sys/arch/alpha/pci/pci_kn8ae.c:1.30 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/pci/pci_kn8ae.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_kn8ae.c,v 1.30 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: pci_kn8ae.c,v 1.31 2020/09/25 03:40:11 thorpej Exp $ */ /* * Copyright (c) 1997 by Matthew Jacob @@ -32,7 +32,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: pci_kn8ae.c,v 1.30 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_kn8ae.c,v 1.31 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: pci_kn8ae.c, #include <sys/errno.h> #include <sys/malloc.h> #include <sys/device.h> +#include <sys/cpu.h> #include <sys/syslog.h> #include <machine/autoconf.h> @@ -141,7 +142,9 @@ dec_kn8ae_intr_map(const struct pci_atta } pci_decompose_tag(pc, bustag, NULL, &device, NULL); + mutex_enter(&cpu_lock); vec = scb_alloc(kn8ae_spurious, NULL); + mutex_exit(&cpu_lock); if (vec == SCB_ALLOC_FAILED) { printf("dec_kn8ae_intr_map: no vector available for " "device %d pin %d\n", device, buspin); @@ -185,6 +188,7 @@ dec_kn8ae_intr_establish( struct scbvec *scb; u_long vec; int pin, device, hpc; + void (*scb_func)(void *, u_long); const u_int ihv = alpha_pci_intr_handle_get_irq(&ih); const u_int flags = alpha_pci_intr_handle_get_flags(&ih); @@ -192,9 +196,12 @@ dec_kn8ae_intr_establish( pin = IH_PIN(ihv); vec = IH_VEC(ihv); + mutex_enter(&cpu_lock); + scb = &scb_iovectab[SCB_VECTOIDX(vec - SCB_IOVECBASE)]; if (scb->scb_func != kn8ae_spurious) { + mutex_exit(&cpu_lock); printf("dec_kn8ae_intr_establish: vector 0x%lx not mapped\n", vec); return (NULL); @@ -205,17 +212,15 @@ dec_kn8ae_intr_establish( * so we don't have to worry about it (in theory, at least). */ - scb->scb_arg = arg; - alpha_mb(); if (flags & ALPHA_INTR_MPSAFE) { - scb->scb_func = (void (*)(void *, u_long))func; + scb_func = (void (*)(void *, u_long))func; } else { kn8ae_wrapped_pci_intrs[ SCB_VECTOIDX(vec - SCB_IOVECBASE)].ih_fn = func; - alpha_mb(); - scb->scb_func = kn8ae_intr_wrapper; + scb_func = kn8ae_intr_wrapper; } - alpha_mb(); + + scb_set(vec, scb_func, arg); if (device < 4) { hpc = 0; @@ -226,10 +231,12 @@ dec_kn8ae_intr_establish( device -= 8; hpc = 2; } - REGVAL(PCIA_DEVVEC(hpc, device, pin) + ccp->cc_sysbase) = vec; + REGVAL(PCIA_DEVVEC(hpc, device, pin) + ccp->cc_sysbase) = vec; kn8ae_enadis_intr(ccp, ih, 1); + mutex_exit(&cpu_lock); + cookie = (void *) ih.value; return (cookie); @@ -241,17 +248,17 @@ dec_kn8ae_intr_disestablish(pci_chipset_ struct dwlpx_config * const ccp = pc->pc_intr_v; const u_long ihv = (u_long) cookie; pci_intr_handle_t ih = { .value = ihv }; - struct scbvec *scb; u_long vec; vec = IH_VEC(ihv); - scb = &scb_iovectab[SCB_VECTOIDX(vec - SCB_IOVECBASE)]; - __USE(scb); + mutex_enter(&cpu_lock); kn8ae_enadis_intr(ccp, ih, 0); scb_free(vec); + + mutex_exit(&cpu_lock); } static void @@ -267,7 +274,7 @@ kn8ae_enadis_intr(struct dwlpx_config *c const u_int ihv = alpha_pci_intr_handle_get_irq(&ih); unsigned long paddr; uint32_t val; - int ionode, hose, device, hpc, busp, s; + int ionode, hose, device, hpc, busp; ionode = sc->dwlpx_node - 4; hose = sc->dwlpx_hosenum; @@ -299,8 +306,8 @@ kn8ae_enadis_intr(struct dwlpx_config *c printf("kn8ae_%s_intr: ihv %x imsk 0x%x hpc %d TLSB node %d hose %d\n", onoff? "enable" : "disable", ihv, val, hpc, ionode + 4, hose); #endif - s = splhigh(); + const u_long psl = alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH); REGVAL(PCIA_IMASK(hpc) + paddr) = val; alpha_mb(); - (void) splx(s); + alpha_pal_swpipl(psl); } Index: src/sys/arch/alpha/pci/pci_machdep.c diff -u src/sys/arch/alpha/pci/pci_machdep.c:1.25 src/sys/arch/alpha/pci/pci_machdep.c:1.26 --- src/sys/arch/alpha/pci/pci_machdep.c:1.25 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/pci/pci_machdep.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep.c,v 1.25 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.26 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.25 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.26 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -70,6 +70,7 @@ __KERNEL_RCSID(0, "$NetBSD: pci_machdep. #include <sys/systm.h> #include <sys/errno.h> #include <sys/device.h> +#include <sys/cpu.h> #include <dev/isa/isavar.h> #include <dev/pci/pcireg.h> @@ -234,15 +235,29 @@ alpha_pci_generic_intr_establish(pci_chi KASSERT(irq < pc->pc_nirq); - cookie = alpha_shared_intr_establish(pc->pc_shared_intrs, + cookie = alpha_shared_intr_alloc_intrhand(pc->pc_shared_intrs, irq, IST_LEVEL, level, flags, func, arg, pc->pc_intr_desc); - if (cookie != NULL && - alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { + if (cookie == NULL) + return NULL; + + mutex_enter(&cpu_lock); + + if (! alpha_shared_intr_link(pc->pc_shared_intrs, cookie, + pc->pc_intr_desc)) { + mutex_exit(&cpu_lock); + alpha_shared_intr_free_intrhand(cookie); + return NULL; + } + + if (alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { scb_set(pc->pc_vecbase + SCB_IDXTOVEC(irq), alpha_pci_generic_iointr, pc); pc->pc_intr_enable(pc, irq); } + + mutex_exit(&cpu_lock); + return cookie; } @@ -252,20 +267,21 @@ alpha_pci_generic_intr_disestablish(pci_ { struct alpha_shared_intrhand * const ih = cookie; const u_int irq = ih->ih_num; - int s; - s = splhigh(); + mutex_enter(&cpu_lock); - alpha_shared_intr_disestablish(pc->pc_shared_intrs, cookie, - pc->pc_intr_desc); - if (alpha_shared_intr_isactive(pc->pc_shared_intrs, irq) == 0) { + if (alpha_shared_intr_firstactive(pc->pc_shared_intrs, irq)) { pc->pc_intr_disable(pc, irq); alpha_shared_intr_set_dfltsharetype(pc->pc_shared_intrs, irq, IST_NONE); scb_free(pc->pc_vecbase + SCB_IDXTOVEC(irq)); } - splx(s); + alpha_shared_intr_unlink(pc->pc_shared_intrs, cookie, pc->pc_intr_desc); + + mutex_exit(&cpu_lock); + + alpha_shared_intr_free_intrhand(cookie); } void Index: src/sys/arch/alpha/pci/sio_pic.c diff -u src/sys/arch/alpha/pci/sio_pic.c:1.44 src/sys/arch/alpha/pci/sio_pic.c:1.45 --- src/sys/arch/alpha/pci/sio_pic.c:1.44 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/pci/sio_pic.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: sio_pic.c,v 1.44 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: sio_pic.c,v 1.45 2020/09/25 03:40:11 thorpej Exp $ */ /*- * Copyright (c) 1998, 2000, 2020 The NetBSD Foundation, Inc. @@ -59,12 +59,13 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: sio_pic.c,v 1.44 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sio_pic.c,v 1.45 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/malloc.h> +#include <sys/cpu.h> #include <sys/syslog.h> #include <machine/intr.h> @@ -444,29 +445,38 @@ sio_intr_establish(void *v, int irq, int if (irq > ICU_LEN || type == IST_NONE) panic("sio_intr_establish: bogus irq or type"); - cookie = alpha_shared_intr_establish(sio_intr, irq, type, level, + cookie = alpha_shared_intr_alloc_intrhand(sio_intr, irq, type, level, flags, fn, arg, "isa irq"); - if (cookie != NULL && - alpha_shared_intr_firstactive(sio_intr, irq)) { + if (cookie == NULL) + return NULL; + + mutex_enter(&cpu_lock); + + if (! alpha_shared_intr_link(sio_intr, cookie, "isa irq")) { + mutex_exit(&cpu_lock); + alpha_shared_intr_free_intrhand(cookie); + return NULL; + } + + if (alpha_shared_intr_firstactive(sio_intr, irq)) { scb_set(0x800 + SCB_IDXTOVEC(irq), sio_iointr, NULL); sio_setirqstat(irq, 1, alpha_shared_intr_get_sharetype(sio_intr, irq)); } - return (cookie); + mutex_exit(&cpu_lock); + + return cookie; } void sio_intr_disestablish(void *v, void *cookie) { struct alpha_shared_intrhand *ih = cookie; - int s, ist, irq = ih->ih_num; + int ist, irq = ih->ih_num; - s = splhigh(); - - /* Remove it from the link. */ - alpha_shared_intr_disestablish(sio_intr, cookie, "isa irq"); + mutex_enter(&cpu_lock); /* * Decide if we should disable the interrupt. We must ensure @@ -475,7 +485,7 @@ sio_intr_disestablish(void *v, void *coo * - An initially-enabled interrupt is never disabled. * - An initially-LT interrupt is never untyped. */ - if (alpha_shared_intr_isactive(sio_intr, irq) == 0) { + if (alpha_shared_intr_firstactive(sio_intr, irq)) { /* * IRQs 0, 1, 8, and 13 must always be edge-triggered * (see setup). @@ -503,7 +513,12 @@ sio_intr_disestablish(void *v, void *coo scb_free(0x800 + SCB_IDXTOVEC(irq)); } - splx(s); + /* Remove it from the link. */ + alpha_shared_intr_unlink(sio_intr, cookie, "isa irq"); + + mutex_exit(&cpu_lock); + + alpha_shared_intr_free_intrhand(cookie); } const char * Index: src/sys/arch/alpha/tc/tc_3000_300.c diff -u src/sys/arch/alpha/tc/tc_3000_300.c:1.36 src/sys/arch/alpha/tc/tc_3000_300.c:1.37 --- src/sys/arch/alpha/tc/tc_3000_300.c:1.36 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/tc/tc_3000_300.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: tc_3000_300.c,v 1.36 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: tc_3000_300.c,v 1.37 2020/09/25 03:40:11 thorpej Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -29,12 +29,13 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: tc_3000_300.c,v 1.36 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tc_3000_300.c,v 1.37 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/malloc.h> +#include <sys/cpu.h> #include <machine/autoconf.h> #include <machine/pte.h> @@ -143,9 +144,18 @@ tc_3000_300_intr_establish(device_t tcad if (tc_3000_300_intr[dev].tci_func != tc_3000_300_intrnull) panic("tc_3000_300_intr_establish: cookie %lu twice", dev); + const int s = splhigh(); + + /* All TC systems are uniprocessors. */ + KASSERT(CPU_IS_PRIMARY(curcpu())); + KASSERT(ncpu == 1); + curcpu()->ci_nintrhand++; + tc_3000_300_intr[dev].tci_func = func; tc_3000_300_intr[dev].tci_arg = arg; + splx(s); + imskp = (volatile uint32_t *)(DEC_3000_300_IOASIC_ADDR + IOASIC_IMSK); switch (dev) { case TC_3000_300_DEV_OPT0: @@ -187,8 +197,14 @@ tc_3000_300_intr_disestablish(device_t t break; } + const int s = splhigh(); + + curcpu()->ci_nintrhand--; + tc_3000_300_intr[dev].tci_func = tc_3000_300_intrnull; tc_3000_300_intr[dev].tci_arg = (void *)dev; + + splx(s); } int Index: src/sys/arch/alpha/tc/tc_3000_500.c diff -u src/sys/arch/alpha/tc/tc_3000_500.c:1.35 src/sys/arch/alpha/tc/tc_3000_500.c:1.36 --- src/sys/arch/alpha/tc/tc_3000_500.c:1.35 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/tc/tc_3000_500.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: tc_3000_500.c,v 1.35 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: tc_3000_500.c,v 1.36 2020/09/25 03:40:11 thorpej Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -29,12 +29,13 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: tc_3000_500.c,v 1.35 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tc_3000_500.c,v 1.36 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> #include <sys/malloc.h> +#include <sys/cpu.h> #include <machine/autoconf.h> #include <machine/pte.h> @@ -166,9 +167,18 @@ tc_3000_500_intr_establish(device_t tcad if (tc_3000_500_intr[dev].tci_func != tc_3000_500_intrnull) panic("tc_3000_500_intr_establish: cookie %lu twice", dev); + const int s = splhigh(); + + /* All TC systems are uniprocessors. */ + KASSERT(CPU_IS_PRIMARY(curcpu())); + KASSERT(ncpu == 1); + curcpu()->ci_nintrhand++; + tc_3000_500_intr[dev].tci_func = func; tc_3000_500_intr[dev].tci_arg = arg; + splx(s); + tc_3000_500_imask &= ~tc_3000_500_intrbits[dev]; *(volatile uint32_t *)TC_3000_500_IMR_WRITE = tc_3000_500_imask; tc_mb(); @@ -191,8 +201,14 @@ tc_3000_500_intr_disestablish(device_t t *(volatile uint32_t *)TC_3000_500_IMR_WRITE = tc_3000_500_imask; tc_mb(); + const int s = splhigh(); + + curcpu()->ci_nintrhand--; + tc_3000_500_intr[dev].tci_func = tc_3000_500_intrnull; tc_3000_500_intr[dev].tci_arg = (void *)dev; + + splx(s); } int Index: src/sys/arch/alpha/tc/tcasic.c diff -u src/sys/arch/alpha/tc/tcasic.c:1.48 src/sys/arch/alpha/tc/tcasic.c:1.49 --- src/sys/arch/alpha/tc/tcasic.c:1.48 Tue Sep 22 15:24:02 2020 +++ src/sys/arch/alpha/tc/tcasic.c Fri Sep 25 03:40:11 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: tcasic.c,v 1.48 2020/09/22 15:24:02 thorpej Exp $ */ +/* $NetBSD: tcasic.c,v 1.49 2020/09/25 03:40:11 thorpej Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. @@ -32,10 +32,11 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: tcasic.c,v 1.48 2020/09/22 15:24:02 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tcasic.c,v 1.49 2020/09/25 03:40:11 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/cpu.h> #include <sys/device.h> #include <machine/autoconf.h> @@ -145,7 +146,9 @@ tcasicattach(device_t parent, device_t s (*intr_setup)(); /* They all come in at 0x800. */ + mutex_enter(&cpu_lock); scb_set(0x800, iointr, NULL); + mutex_exit(&cpu_lock); config_found(self, &tba, tcasicprint); }