Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/alpha/common - Fix some bugs in previous, mainly re...



details:   https://anonhg.NetBSD.org/src/rev/01a032243aad
branches:  trunk
changeset: 939350:01a032243aad
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sat Sep 26 02:35:31 2020 +0000

description:
- 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.

diffstat:

 sys/arch/alpha/common/shared_intr.c |  92 ++++++++++++++++++++++++++++++++----
 1 files changed, 81 insertions(+), 11 deletions(-)

diffs (155 lines):

diff -r 5d4da1c33444 -r 01a032243aad sys/arch/alpha/common/shared_intr.c
--- a/sys/arch/alpha/common/shared_intr.c       Sat Sep 26 00:03:29 2020 +0000
+++ b/sys/arch/alpha/common/shared_intr.c       Sat Sep 26 02:35:31 2020 +0000
@@ -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 @@
 {
        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 @@
         * 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 @@
 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 @@
        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 *



Home | Main Index | Thread Index | Old Index