void cpu_intr(struct trapframe *tf) { struct intr_event *event; register_t cause, status; int hard, i, intr; critical_enter(); cause = mips_rd_cause(); status = mips_rd_status(); intr = (cause & MIPS_INT_MASK) >> 8; /* * Do not handle masked interrupts. They were masked by * pre_ithread function (mips_mask_XXX_intr) and will be * unmasked once ithread is through with handler */ intr &= (status & MIPS_INT_MASK) >> 8; while ((i = fls(intr)) != 0) { intr &= ~(1 << (i - 1)); switch (i) { case 1: case 2: /* Software interrupt. */ i--; /* Get a 0-offset interrupt. */ hard = 0; event = softintr_events[i]; mips_intrcnt_inc(mips_intr_counters[i]); break; default: /* Hardware interrupt. */ i -= 2; /* Trim software interrupt bits. */ i--; /* Get a 0-offset interrupt. */ hard = 1; event = hardintr_events[i]; mips_intrcnt_inc(mips_intr_counters[NSOFT_IRQS + i]); break; } if (!event || TAILQ_EMPTY(&event->ie_handlers)) { printf("stray %s interrupt %d\n", hard ? "hard" : "soft", i); continue; } if (intr_event_handle(event, tf) != 0) { printf("stray %s interrupt %d\n", hard ? "hard" : "soft", i); } } KASSERT(i == 0, ("all interrupts handled")); critical_exit(); #ifdef HWPMC_HOOKS if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN)) pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf); #endif }
static int apb_filter(void *arg) { struct apb_softc *sc = arg; struct intr_event *event; uint32_t reg, irq; struct thread *td; struct trapframe *tf; reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS); for (irq = 0; irq < APB_NIRQS; irq++) { if (reg & (1 << irq)) { switch (ar71xx_soc) { case AR71XX_SOC_AR7240: case AR71XX_SOC_AR7241: case AR71XX_SOC_AR7242: case AR71XX_SOC_AR9330: case AR71XX_SOC_AR9331: case AR71XX_SOC_AR9341: case AR71XX_SOC_AR9342: case AR71XX_SOC_AR9344: /* ACK/clear the given interrupt */ ATH_WRITE_REG(AR71XX_MISC_INTR_STATUS, (1 << irq)); break; default: /* fallthrough */ break; } event = sc->sc_eventstab[irq]; if (!event || TAILQ_EMPTY(&event->ie_handlers)) { if (irq == APB_INTR_PMC) { td = PCPU_GET(curthread); tf = td->td_intr_frame; if (pmc_intr) (*pmc_intr)(PCPU_GET(cpuid), tf); mips_intrcnt_inc(sc->sc_intr_counter[irq]); continue; } /* Ignore timer interrupts */ if (irq != 0 && irq != 8 && irq != 9 && irq != 10) printf("Stray APB IRQ %d\n", irq); continue; } intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame); mips_intrcnt_inc(sc->sc_intr_counter[irq]); } } return (FILTER_HANDLED); }
static int ciu_intr(void *arg) { struct ciu_softc *sc; uint64_t en0_sum, en1_sum; uint64_t en0_mask, en1_mask; int irq_index; int error; sc = arg; (void)sc; en0_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(cvmx_get_core_num()*2)); en1_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1); en0_mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2)); en1_mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2)); en0_sum &= en0_mask; en1_sum &= en1_mask; if (en0_sum == 0 && en1_sum == 0) return (FILTER_STRAY); irq_index = 0; for (irq_index = 0; en0_sum != 0; irq_index++, en0_sum >>= 1) { if ((en0_sum & 1) == 0) continue; mips_intrcnt_inc(ciu_en0_intrcnt[irq_index]); error = intr_event_handle(ciu_en0_intr_events[irq_index], NULL); if (error != 0) printf("%s: stray en0 irq%d\n", __func__, irq_index); } irq_index = 0; for (irq_index = 0; en1_sum != 0; irq_index++, en1_sum >>= 1) { if ((en1_sum & 1) == 0) continue; mips_intrcnt_inc(ciu_en1_intrcnt[irq_index]); error = intr_event_handle(ciu_en1_intr_events[irq_index], NULL); if (error != 0) printf("%s: stray en1 irq%d\n", __func__, irq_index); } return (FILTER_HANDLED); }
void cpu_intr(struct trapframe *tf) { struct intr_event *ie; uint64_t eirr, eimr; int i; critical_enter(); /* find a list of enabled interrupts */ eirr = read_c0_eirr64(); eimr = read_c0_eimr64(); eirr &= eimr; if (eirr == 0) { critical_exit(); return; } /* * No need to clear the EIRR here as the handler writes to * compare which ACKs the interrupt. */ if (eirr & (1 << IRQ_TIMER)) { intr_event_handle(xlr_interrupts[IRQ_TIMER].ie, tf); critical_exit(); return; } /* FIXME sched pin >? LOCK>? */ for (i = sizeof(eirr) * 8 - 1; i >= 0; i--) { if ((eirr & (1ULL << i)) == 0) continue; ie = xlr_interrupts[i].ie; /* Don't account special IRQs */ switch (i) { case IRQ_IPI: case IRQ_MSGRING: break; default: mips_intrcnt_inc(mips_intr_counters[i]); } /* Ack the IRQ on the CPU */ write_c0_eirr64(1ULL << i); if (intr_event_handle(ie, tf) != 0) { printf("stray interrupt %d\n", i); } } critical_exit(); }
static int apb_filter(void *arg) { struct apb_softc *sc = arg; struct intr_event *event; uint32_t reg, irq; if(ar531x_soc >= AR531X_SOC_AR5315) reg = ATH_READ_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_MISC_INTSTAT); else reg = ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTSTAT); for (irq = 0; irq < APB_NIRQS; irq++) { if (reg & (1 << irq)) { if(ar531x_soc >= AR531X_SOC_AR5315) { ATH_WRITE_REG(AR5315_SYSREG_BASE + AR5315_SYSREG_MISC_INTSTAT, reg & ~(1 << irq)); } else { ATH_WRITE_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_MISC_INTSTAT, reg & ~(1 << irq)); } event = sc->sc_eventstab[irq]; if (!event || TAILQ_EMPTY(&event->ie_handlers)) { if(irq == 1 && ar531x_soc < AR531X_SOC_AR5315) { ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_AHBPERR); ATH_READ_REG(AR5312_SYSREG_BASE + AR5312_SYSREG_AHBDMAE); } /* Ignore non handle interrupts */ if (irq != 0 && irq != 6) printf("Stray APB IRQ %d\n", irq); continue; } intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame); mips_intrcnt_inc(sc->sc_intr_counter[irq]); } } return (FILTER_HANDLED); }
static int apb_intr(void *arg) { struct apb_softc *sc = arg; struct intr_event *event; uint32_t reg, irq; reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS); for (irq = 0; irq < APB_NIRQS; irq++) { if (reg & (1 << irq)) { switch (ar71xx_soc) { case AR71XX_SOC_AR7240: case AR71XX_SOC_AR7241: case AR71XX_SOC_AR7242: /* Ack/clear the irq on status register for AR724x */ ATH_WRITE_REG(AR71XX_MISC_INTR_STATUS, reg & ~(1 << irq)); break; default: /* fallthrough */ break; } event = sc->sc_eventstab[irq]; if (!event || TAILQ_EMPTY(&event->ie_handlers)) { /* Ignore timer interrupts */ if (irq != 0) printf("Stray APB IRQ %d\n", irq); continue; } /* TODO: frame instead of NULL? */ intr_event_handle(event, NULL); mips_intrcnt_inc(sc->sc_intr_counter[irq]); } } return (FILTER_HANDLED); }