ether82563, etheriwl, pmmc: fix potential multiprocessor races with wakeup
make sure that the wakeup enable conditions are seen by different processors before sleep is called. the problems havnt been observed so far.
This commit is contained in:
parent
ac52599eef
commit
2009d55643
3 changed files with 27 additions and 32 deletions
|
@ -1053,7 +1053,9 @@ i82563replenish(Ctlr *ctlr, int maysleep)
|
|||
print("i82563%d: no rx buffers\n", ctlr->pool);
|
||||
if(maysleep == 0)
|
||||
return -1;
|
||||
ilock(p);
|
||||
p->starve = 1;
|
||||
iunlock(p);
|
||||
sleep(p, icansleep, p);
|
||||
goto redux;
|
||||
}
|
||||
|
|
|
@ -349,7 +349,6 @@ struct Ctlr {
|
|||
Rendez;
|
||||
u32int m;
|
||||
u32int w;
|
||||
u32int r;
|
||||
} wait;
|
||||
|
||||
struct {
|
||||
|
@ -1014,39 +1013,35 @@ readfirmware(char *name)
|
|||
return fw;
|
||||
}
|
||||
|
||||
typedef struct Irqwait Irqwait;
|
||||
struct Irqwait {
|
||||
Ctlr *ctlr;
|
||||
u32int mask;
|
||||
};
|
||||
|
||||
static int
|
||||
gotirq(void *arg)
|
||||
{
|
||||
Irqwait *w;
|
||||
Ctlr *ctlr;
|
||||
|
||||
w = arg;
|
||||
ctlr = w->ctlr;
|
||||
ctlr->wait.r = ctlr->wait.m & w->mask;
|
||||
if(ctlr->wait.r){
|
||||
ctlr->wait.m &= ~ctlr->wait.r;
|
||||
return 1;
|
||||
}
|
||||
ctlr->wait.w = w->mask;
|
||||
return 0;
|
||||
Ctlr *ctlr = arg;
|
||||
return (ctlr->wait.m & ctlr->wait.w) != 0;
|
||||
}
|
||||
|
||||
static u32int
|
||||
irqwait(Ctlr *ctlr, u32int mask, int timeout)
|
||||
{
|
||||
Irqwait w;
|
||||
u32int r;
|
||||
|
||||
w.ctlr = ctlr;
|
||||
w.mask = mask;
|
||||
tsleep(&ctlr->wait, gotirq, &w, timeout);
|
||||
ctlr->wait.w = 0;
|
||||
return ctlr->wait.r & mask;
|
||||
ilock(ctlr);
|
||||
r = ctlr->wait.m & mask;
|
||||
if(r == 0){
|
||||
ctlr->wait.w = mask;
|
||||
iunlock(ctlr);
|
||||
if(!waserror()){
|
||||
tsleep(&ctlr->wait, gotirq, ctlr, timeout);
|
||||
poperror();
|
||||
}
|
||||
ilock(ctlr);
|
||||
ctlr->wait.w = 0;
|
||||
r = ctlr->wait.m & mask;
|
||||
}
|
||||
ctlr->wait.m &= ~r;
|
||||
iunlock(ctlr);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1206,7 +1201,7 @@ reset(Ctlr *ctlr)
|
|||
csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
|
||||
|
||||
ctlr->broken = 0;
|
||||
ctlr->wait.r = 0;
|
||||
ctlr->wait.m = 0;
|
||||
ctlr->wait.w = 0;
|
||||
|
||||
ctlr->ie = Idefmask;
|
||||
|
@ -2197,11 +2192,8 @@ iwlinterrupt(Ureg*, void *arg)
|
|||
dumpctlr(ctlr);
|
||||
}
|
||||
ctlr->wait.m |= isr;
|
||||
if(ctlr->wait.m & ctlr->wait.w){
|
||||
ctlr->wait.r = ctlr->wait.m & ctlr->wait.w;
|
||||
ctlr->wait.m &= ~ctlr->wait.r;
|
||||
if(ctlr->wait.m & ctlr->wait.w)
|
||||
wakeup(&ctlr->wait);
|
||||
}
|
||||
done:
|
||||
csr32w(ctlr, Imr, ctlr->ie);
|
||||
iunlock(ctlr);
|
||||
|
|
|
@ -362,7 +362,9 @@ intrwait(Ctlr *c, u32int mask, int tmo)
|
|||
{
|
||||
u32int status;
|
||||
|
||||
ilock(c);
|
||||
c->waitmsk = Seint | mask;
|
||||
iunlock(c);
|
||||
do {
|
||||
if(!waserror()){
|
||||
tsleep(&c->r, waitcond, c, 100);
|
||||
|
@ -373,11 +375,10 @@ intrwait(Ctlr *c, u32int mask, int tmo)
|
|||
break;
|
||||
tmo -= 100;
|
||||
} while(tmo > 0);
|
||||
|
||||
ilock(c);
|
||||
c->waitmsk = 0;
|
||||
status = c->waitsts;
|
||||
c->waitsts &= ~(status & mask);
|
||||
c->waitmsk = 0;
|
||||
if((status & mask) == 0 || (status & Seint) != 0){
|
||||
/* abort command on timeout/error interrupt */
|
||||
softreset(c, 0);
|
||||
|
@ -386,7 +387,7 @@ intrwait(Ctlr *c, u32int mask, int tmo)
|
|||
}
|
||||
iunlock(c);
|
||||
|
||||
return status;
|
||||
return status & mask;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue