diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-12-22 16:10:18 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-12-22 16:10:18 +0100 |
commit | e0c221eea6b68c87f89eb073d7204851398fc5d8 (patch) | |
tree | 121a7eeb0995e8a8a9cd6d4a3a2140d755609b1a /sys/src/9/pc/trap.c | |
parent | b486d8871b3ae20745f32b9d509d75d5a911ec65 (diff) |
pc, pc64: fix intrdisable() to remove the Vctl entry even tho we can't disable the interrupt on apic
Diffstat (limited to 'sys/src/9/pc/trap.c')
-rw-r--r-- | sys/src/9/pc/trap.c | 53 |
1 files changed, 32 insertions, 21 deletions
diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c index 51961577b..1eef90ea9 100644 --- a/sys/src/9/pc/trap.c +++ b/sys/src/9/pc/trap.c @@ -82,29 +82,40 @@ intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name) Vctl **pv, *v; int vno; - /* - * For now, none of this will work with the APIC code, - * there is no mapping between irq and vector as the IRQ - * is pretty meaningless. - */ - if(arch->intrvecno == nil) - return -1; - vno = arch->intrvecno(irq); + if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){ + /* + * on APIC machine, irq is pretty meaningless + * and disabling a the vector is not implemented. + * however, we still want to remove the matching + * Vctl entry to prevent calling Vctl.f() with a + * stale Vctl.a pointer. + */ + irq = -1; + vno = VectorPIC; + } else { + vno = arch->intrvecno(irq); + } ilock(&vctllock); - pv = &vctl[vno]; - while (*pv && - ((*pv)->irq != irq || (*pv)->tbdf != tbdf || (*pv)->f != f || (*pv)->a != a || - strcmp((*pv)->name, name))) - pv = &((*pv)->next); - assert(*pv); - - v = *pv; - *pv = (*pv)->next; /* Link out the entry */ - - if(vctl[vno] == nil && arch->intrdisable != nil) - arch->intrdisable(irq); + for(; vno <= MaxIrqLAPIC; vno++){ + for(pv = &vctl[vno]; (v = *pv) != nil; pv = &v->next){ + if(v->isintr && (v->irq == irq || irq == -1) + && v->tbdf == tbdf && v->f == f && v->a == a + && strcmp(v->name, name) == 0) + break; + } + if(v != nil){ + *pv = v->next; + xfree(v); + + if(irq == -1) + break; + if(vctl[vno] == nil && arch->intrdisable != nil) + arch->intrdisable(irq); + } + if(irq != -1) + break; + } iunlock(&vctllock); - xfree(v); return 0; } |