diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2016-12-02 15:01:08 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2016-12-02 15:01:08 +0000 |
commit | 89f6201dfb6ff4f37f923936d1965caaa084b257 (patch) | |
tree | e7e8600de6a81207a21f1ef7c70b8b9e478e3a83 /sys | |
parent | 8cf28d0984027144dd8b75f963271b1bfdc55a16 (diff) |
Simplify interrupt dispatching by processing requests without
prioritization by IPL.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/octeon/dev/octeon_intr.c | 147 |
1 files changed, 73 insertions, 74 deletions
diff --git a/sys/arch/octeon/dev/octeon_intr.c b/sys/arch/octeon/dev/octeon_intr.c index 0e9010add61..d592f129a45 100644 --- a/sys/arch/octeon/dev/octeon_intr.c +++ b/sys/arch/octeon/dev/octeon_intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: octeon_intr.c,v 1.14 2016/11/20 15:02:25 visa Exp $ */ +/* $OpenBSD: octeon_intr.c,v 1.15 2016/12/02 15:01:07 visa Exp $ */ /* * Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se) @@ -211,6 +211,26 @@ octeon_intr_makemasks() octeon_imask[cpuid][IPL_NONE] = 0; } +static inline int +octeon_next_irq(uint64_t *isr) +{ + uint64_t irq, tmp = *isr; + + if (tmp == 0) + return -1; + + asm volatile ( + " .set push\n" + " .set mips64\n" + " dclz %0, %0\n" + " .set pop\n" + : "=r" (tmp) : "0" (tmp)); + + irq = 63u - tmp; + *isr &= ~(1u << irq); + return irq; +} + /* * Interrupt dispatcher. */ @@ -218,18 +238,18 @@ uint32_t octeon_iointr(uint32_t hwpend, struct trapframe *frame) { struct cpu_info *ci = curcpu(); - int cpuid = cpu_number(); - uint64_t imr, isr, mask; - int ipl; - int bit; struct intrhand *ih; - int rc; - uint64_t sum0 = CIU_IP2_SUM0(cpuid); - uint64_t en0 = CIU_IP2_EN0(cpuid); + uint64_t imr, isr, mask; + uint64_t en0 = CIU_IP2_EN0(ci->ci_cpuid); + uint64_t sum0 = CIU_IP2_SUM0(ci->ci_cpuid); + int handled, ipl, irq; +#ifdef MULTIPROCESSOR + register_t sr; + int need_lock; +#endif isr = bus_space_read_8(&iobus_tag, iobus_h, sum0); imr = bus_space_read_8(&iobus_tag, iobus_h, en0); - bit = 63; isr &= imr; if (isr == 0) @@ -244,85 +264,64 @@ octeon_iointr(uint32_t hwpend, struct trapframe *frame) * If interrupts are spl-masked, mask them and wait for splx() * to reenable them when necessary. */ - if ((mask = isr & octeon_imask[cpuid][frame->ipl]) != 0) { + if ((mask = isr & octeon_imask[ci->ci_cpuid][frame->ipl]) != 0) { isr &= ~mask; imr &= ~mask; } + if (isr == 0) + return hwpend; /* * Now process allowed interrupts. */ - if (isr != 0) { - int lvl, bitno; - uint64_t tmpisr; - - __asm__ (".set noreorder\n"); - ipl = ci->ci_ipl; - mips_sync(); - __asm__ (".set reorder\n"); - - /* Service higher level interrupts first */ - for (lvl = NIPLS - 1; lvl != IPL_NONE; lvl--) { - tmpisr = isr & (octeon_imask[cpuid][lvl] ^ octeon_imask[cpuid][lvl - 1]); - if (tmpisr == 0) - continue; - for (bitno = bit, mask = 1UL << bitno; mask != 0; - bitno--, mask >>= 1) { - if ((tmpisr & mask) == 0) - continue; - - rc = 0; - for (ih = octeon_intrhand[bitno]; ih != NULL; - ih = ih->ih_next) { -#ifdef MULTIPROCESSOR - register_t sr; - int need_lock; -#endif - splraise(ih->ih_level); + + __asm__ (".set noreorder\n"); + ipl = ci->ci_ipl; + mips_sync(); + __asm__ (".set reorder\n"); + + while ((irq = octeon_next_irq(&isr)) >= 0) { + handled = 0; + for (ih = octeon_intrhand[irq]; ih != NULL; ih = ih->ih_next) { + splraise(ih->ih_level); #ifdef MULTIPROCESSOR - if (ih->ih_level < IPL_IPI) { - sr = getsr(); - ENABLEIPI(); - } - if (ih->ih_flags & IH_MPSAFE) - need_lock = 0; - else - need_lock = - ih->ih_level < IPL_CLOCK; - if (need_lock) - __mp_lock(&kernel_lock); + if (ih->ih_level < IPL_IPI) { + sr = getsr(); + ENABLEIPI(); + } + if (ih->ih_flags & IH_MPSAFE) + need_lock = 0; + else + need_lock = ih->ih_level < IPL_CLOCK; + if (need_lock) + __mp_lock(&kernel_lock); #endif - if ((*ih->ih_fun)(ih->ih_arg) != 0) { - rc = 1; - atomic_inc_long((unsigned long *) - &ih->ih_count.ec_count); - } + if ((*ih->ih_fun)(ih->ih_arg) != 0) { + handled = 1; + atomic_inc_long( + (unsigned long *)&ih->ih_count.ec_count); + } #ifdef MULTIPROCESSOR - if (need_lock) - __mp_unlock(&kernel_lock); - if (ih->ih_level < IPL_IPI) - setsr(sr); + if (need_lock) + __mp_unlock(&kernel_lock); + if (ih->ih_level < IPL_IPI) + setsr(sr); #endif - __asm__ (".set noreorder\n"); - ci->ci_ipl = ipl; - mips_sync(); - __asm__ (".set reorder\n"); - } - if (rc == 0) - printf("spurious interrupt %d\n", bitno); - - isr ^= mask; - if ((tmpisr ^= mask) == 0) - break; - } } - - /* - * Reenable interrupts which have been serviced. - */ - bus_space_write_8(&iobus_tag, iobus_h, en0, imr); + if (!handled) + printf("spurious interrupt %d\n", irq); } + __asm__ (".set noreorder\n"); + ci->ci_ipl = ipl; + mips_sync(); + __asm__ (".set reorder\n"); + + /* + * Reenable interrupts which have been serviced. + */ + bus_space_write_8(&iobus_tag, iobus_h, en0, imr); + return hwpend; } |