Module Name: src Committed By: thorpej Date: Sat Sep 26 02:35:31 UTC 2020
Modified Files: src/sys/arch/alpha/common: shared_intr.c Log Message: - Fix some bugs in previous, mainly related to indexing the correct interrupt queue. - Make sure to update cpu_info::ci_nintrhand if an irq moves from one CPU to another. To generate a diff of this commit: cvs rdiff -u -r1.25 -r1.26 src/sys/arch/alpha/common/shared_intr.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/common/shared_intr.c diff -u src/sys/arch/alpha/common/shared_intr.c:1.25 src/sys/arch/alpha/common/shared_intr.c:1.26 --- src/sys/arch/alpha/common/shared_intr.c:1.25 Fri Sep 25 03:40:11 2020 +++ src/sys/arch/alpha/common/shared_intr.c Sat Sep 26 02:35:31 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: shared_intr.c,v 1.25 2020/09/25 03:40:11 thorpej Exp $ */ +/* $NetBSD: shared_intr.c,v 1.26 2020/09/26 02:35:31 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: shared_intr.c,v 1.25 2020/09/25 03:40:11 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: shared_intr.c,v 1.26 2020/09/26 02:35:31 thorpej Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -212,9 +212,11 @@ alpha_shared_intr_link_unlink_xcall(void { 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; + struct cpu_info *ci = intr[num].intr_cpu; + + KASSERT(ci != NULL); KASSERT(ci == curcpu() || !mp_online); KASSERT(!cpu_intr_p()); @@ -273,17 +275,17 @@ alpha_shared_intr_link(struct alpha_shar * If a CPU hasn't been assigned yet, just give it to the * primary. */ - if (intr->intr_cpu == NULL) { - intr->intr_cpu = &cpu_info_primary; + if (intr[num].intr_cpu == NULL) { + intr[num].intr_cpu = &cpu_info_primary; } kpreempt_disable(); - if (intr->intr_cpu == curcpu() || !mp_online) { - alpha_shared_intr_link_unlink_xcall(ih, intr); + if (intr[num].intr_cpu == curcpu() || !mp_online) { + alpha_shared_intr_link_unlink_xcall(ih, ih); } else { uint64_t where = xc_unicast(XC_HIGHPRI, - alpha_shared_intr_link_unlink_xcall, ih, intr, - intr->intr_cpu); + alpha_shared_intr_link_unlink_xcall, ih, ih, + intr->intr_cpu); xc_wait(where); } kpreempt_enable(); @@ -295,16 +297,17 @@ void alpha_shared_intr_unlink(struct alpha_shared_intr *intr, struct alpha_shared_intrhand *ih, const char *basename) { + unsigned int num = ih->ih_num; KASSERT(mutex_owned(&cpu_lock)); kpreempt_disable(); - if (intr->intr_cpu == curcpu() || !mp_online) { + if (intr[num].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); + intr->intr_cpu); xc_wait(where); } kpreempt_enable(); @@ -401,12 +404,79 @@ alpha_shared_intr_get_private(struct alp return (intr[num].intr_private); } +static unsigned int +alpha_shared_intr_q_count_handlers(struct alpha_shared_intr *intr_q) +{ + unsigned int cnt = 0; + struct alpha_shared_intrhand *ih; + + TAILQ_FOREACH(ih, &intr_q->intr_q, ih_q) { + cnt++; + } + + return cnt; +} + +static void +alpha_shared_intr_set_cpu_xcall(void *arg1, void *arg2) +{ + struct alpha_shared_intr *intr_q = arg1; + struct cpu_info *ci = arg2; + unsigned int cnt = alpha_shared_intr_q_count_handlers(intr_q); + + KASSERT(ci == curcpu() || !mp_online); + + ci->ci_nintrhand += cnt; + KASSERT(cnt <= ci->ci_nintrhand); +} + +static void +alpha_shared_intr_unset_cpu_xcall(void *arg1, void *arg2) +{ + struct alpha_shared_intr *intr_q = arg1; + struct cpu_info *ci = arg2; + unsigned int cnt = alpha_shared_intr_q_count_handlers(intr_q); + + KASSERT(ci == curcpu() || !mp_online); + + KASSERT(cnt <= ci->ci_nintrhand); + ci->ci_nintrhand -= cnt; +} + void alpha_shared_intr_set_cpu(struct alpha_shared_intr *intr, unsigned int num, struct cpu_info *ci) { + struct cpu_info *old_ci; + + KASSERT(mutex_owned(&cpu_lock)); + old_ci = intr[num].intr_cpu; intr[num].intr_cpu = ci; + + if (old_ci != NULL && old_ci != ci) { + kpreempt_disable(); + + if (ci == curcpu() || !mp_online) { + alpha_shared_intr_set_cpu_xcall(&intr[num], ci); + } else { + uint64_t where = xc_unicast(XC_HIGHPRI, + alpha_shared_intr_set_cpu_xcall, &intr[num], + ci, ci); + xc_wait(where); + } + + if (old_ci == curcpu() || !mp_online) { + alpha_shared_intr_unset_cpu_xcall(&intr[num], old_ci); + } else { + uint64_t where = xc_unicast(XC_HIGHPRI, + alpha_shared_intr_unset_cpu_xcall, &intr[num], + old_ci, old_ci); + xc_wait(where); + } + + kpreempt_enable(); + } } struct cpu_info *