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.
This commit is contained in:
parent
ec32c33db9
commit
d2c7e180a1
|
@ -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. */
|
||||
|
|
Loading…
Reference in New Issue