From d2c7e180a1e8feb7c9ab4e94eb7cd1b020d963d8 Mon Sep 17 00:00:00 2001 From: skrll Date: Sat, 14 Apr 2012 10:43:19 +0000 Subject: [PATCH] Sync with the following OpenBSD changes, but do the shared interrupt reporting differently. Each cpu and device interrupt gets its own counter. revision 1.14 Fix counting of interrupts for devices that attach to elroy(4). Shared interrupts would be counted double, once for the interrupting device and once for the device at the head of the chain. The handlers would run properly though. Avoid this by giving each device its own interrupt counter instead of using the counter provided by the generic interrupt handling code for the head of the chain. revision 1.13 Stop calling shared interrupt handlers as soon as one of them return 1 (positive interrupt was for me), like we do on other architectures. This is done here, at the elroy(4) driver level, since this is where shared PCI interrupts are handled. We could do something similar for dino(4) but this optimization is probably not very relevant there. --- sys/arch/hp700/dev/apic.c | 80 +++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/sys/arch/hp700/dev/apic.c b/sys/arch/hp700/dev/apic.c index 4dec227b13ef..7ad9de404b7a 100644 --- a/sys/arch/hp700/dev/apic.c +++ b/sys/arch/hp700/dev/apic.c @@ -1,6 +1,6 @@ -/* $NetBSD: apic.c,v 1.13 2012/04/03 12:07:26 skrll Exp $ */ +/* $NetBSD: apic.c,v 1.14 2012/04/14 10:43:19 skrll Exp $ */ -/* $OpenBSD: apic.c,v 1.7 2007/10/06 23:50:54 krw Exp $ */ +/* $OpenBSD: apic.c,v 1.14 2011/05/01 21:59:39 kettenis Exp $ */ /* * Copyright (c) 2005 Michael Shalayeff @@ -178,53 +178,61 @@ apic_intr_establish(void *v, pci_intr_handle_t ih, if (aiv == NULL) return NULL; + cnt = malloc(sizeof(struct evcnt), M_DEVBUF, M_NOWAIT); + if (cnt == NULL) { + free(aiv, M_DEVBUF); + return NULL; + } + aiv->sc = sc; aiv->ih = ih; aiv->handler = handler; aiv->arg = arg; aiv->next = NULL; - aiv->cnt = NULL; - if (apic_intr_list[irq]) { - cnt = malloc(sizeof(struct evcnt), M_DEVBUF, M_NOWAIT); - if (cnt == NULL) { + aiv->cnt = cnt; + + biv = apic_intr_list[irq]; + if (biv == NULL) { + iv = hp700_intr_establish(pri, apic_intr, aiv, &ir_cpu, irq); + if (iv == NULL) { free(aiv, M_DEVBUF); + free(cnt, M_DEVBUF); + return NULL; } + } - snprintf(aiv->aiv_name, sizeof(aiv->aiv_name), "line %d irq %d", - line, irq); + snprintf(aiv->aiv_name, sizeof(aiv->aiv_name), "line %d irq %d", + line, irq); - evcnt_attach_dynamic(cnt, EVCNT_TYPE_INTR, NULL, - device_xname(sc->sc_dv), aiv->aiv_name); - biv = apic_intr_list[irq]; + evcnt_attach_dynamic(cnt, EVCNT_TYPE_INTR, NULL, + device_xname(sc->sc_dv), aiv->aiv_name); + + if (biv) { while (biv->next) biv = biv->next; biv->next = aiv; - aiv->cnt = cnt; return arg; } - iv = hp700_intr_establish(pri, apic_intr, aiv, &ir_cpu, irq); - if (iv) { - ent0 = (31 - irq) & APIC_ENT0_VEC; - ent0 |= apic_get_int_ent0(sc, line); + ent0 = (31 - irq) & APIC_ENT0_VEC; + ent0 |= apic_get_int_ent0(sc, line); #if 0 - if (cold) { - sc->sc_imr |= (1 << irq); - ent0 |= APIC_ENT0_MASK; - } -#endif - apic_write(sc->sc_regs, APIC_ENT0(line), APIC_ENT0_MASK); - apic_write(sc->sc_regs, APIC_ENT1(line), - ((hpa & 0x0ff00000) >> 4) | ((hpa & 0x000ff000) << 12)); - apic_write(sc->sc_regs, APIC_ENT0(line), ent0); - - /* Signal EOI. */ - elroy_write32(&r->apic_eoi, - htole32((31 - irq) & APIC_ENT0_VEC)); - - apic_intr_list[irq] = aiv; + if (cold) { + sc->sc_imr |= (1 << irq); + ent0 |= APIC_ENT0_MASK; } +#endif + apic_write(sc->sc_regs, APIC_ENT0(line), APIC_ENT0_MASK); + apic_write(sc->sc_regs, APIC_ENT1(line), + ((hpa & 0x0ff00000) >> 4) | ((hpa & 0x000ff000) << 12)); + apic_write(sc->sc_regs, APIC_ENT0(line), ent0); + + /* Signal EOI. */ + elroy_write32(&r->apic_eoi, + htole32((31 - irq) & APIC_ENT0_VEC)); + + apic_intr_list[irq] = aiv; return (arg); } @@ -244,11 +252,11 @@ apic_intr(void *v) int claimed = 0; while (iv) { - if (iv->handler(iv->arg)) { - if (iv->cnt) - iv->cnt->ev_count++; - claimed = 1; - } + claimed = iv->handler(iv->arg); + if (claimed && iv->cnt) + iv->cnt->ev_count++; + if (claimed) + break; iv = iv->next; } /* Signal EOI. */