pc, pc64: fix intrdisable() to remove the Vctl entry even tho we can't disable the interrupt on apic
This commit is contained in:
parent
b486d8871b
commit
e0c221eea6
2 changed files with 62 additions and 40 deletions
|
@ -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);
|
||||
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);
|
||||
|
||||
v = *pv;
|
||||
*pv = (*pv)->next; /* Link out the entry */
|
||||
|
||||
if(vctl[vno] == nil && arch->intrdisable != nil)
|
||||
arch->intrdisable(irq);
|
||||
if(irq == -1)
|
||||
break;
|
||||
if(vctl[vno] == nil && arch->intrdisable != nil)
|
||||
arch->intrdisable(irq);
|
||||
}
|
||||
if(irq != -1)
|
||||
break;
|
||||
}
|
||||
iunlock(&vctllock);
|
||||
xfree(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
|
||||
v = *pv;
|
||||
*pv = (*pv)->next; /* Link out the entry */
|
||||
|
||||
if(vctl[vno] == nil && arch->intrdisable != nil)
|
||||
arch->intrdisable(irq);
|
||||
if(irq == -1)
|
||||
break;
|
||||
if(vctl[vno] == nil && arch->intrdisable != nil)
|
||||
arch->intrdisable(irq);
|
||||
}
|
||||
if(irq != -1)
|
||||
break;
|
||||
}
|
||||
iunlock(&vctllock);
|
||||
xfree(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue