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
|
@ -1053,7 +1053,9 @@ i82563replenish(Ctlr *ctlr, int maysleep)
|
||||||
print("i82563%d: no rx buffers\n", ctlr->pool);
|
print("i82563%d: no rx buffers\n", ctlr->pool);
|
||||||
if(maysleep == 0)
|
if(maysleep == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
ilock(p);
|
||||||
p->starve = 1;
|
p->starve = 1;
|
||||||
|
iunlock(p);
|
||||||
sleep(p, icansleep, p);
|
sleep(p, icansleep, p);
|
||||||
goto redux;
|
goto redux;
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,7 +349,6 @@ struct Ctlr {
|
||||||
Rendez;
|
Rendez;
|
||||||
u32int m;
|
u32int m;
|
||||||
u32int w;
|
u32int w;
|
||||||
u32int r;
|
|
||||||
} wait;
|
} wait;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -1014,39 +1013,35 @@ readfirmware(char *name)
|
||||||
return fw;
|
return fw;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct Irqwait Irqwait;
|
|
||||||
struct Irqwait {
|
|
||||||
Ctlr *ctlr;
|
|
||||||
u32int mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gotirq(void *arg)
|
gotirq(void *arg)
|
||||||
{
|
{
|
||||||
Irqwait *w;
|
Ctlr *ctlr = arg;
|
||||||
Ctlr *ctlr;
|
return (ctlr->wait.m & ctlr->wait.w) != 0;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32int
|
static u32int
|
||||||
irqwait(Ctlr *ctlr, u32int mask, int timeout)
|
irqwait(Ctlr *ctlr, u32int mask, int timeout)
|
||||||
{
|
{
|
||||||
Irqwait w;
|
u32int r;
|
||||||
|
|
||||||
w.ctlr = ctlr;
|
ilock(ctlr);
|
||||||
w.mask = mask;
|
r = ctlr->wait.m & mask;
|
||||||
tsleep(&ctlr->wait, gotirq, &w, timeout);
|
if(r == 0){
|
||||||
ctlr->wait.w = 0;
|
ctlr->wait.w = mask;
|
||||||
return ctlr->wait.r & 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
|
static int
|
||||||
|
@ -1206,7 +1201,7 @@ reset(Ctlr *ctlr)
|
||||||
csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
|
csr32w(ctlr, UcodeGp1Clr, UcodeGp1CmdBlocked);
|
||||||
|
|
||||||
ctlr->broken = 0;
|
ctlr->broken = 0;
|
||||||
ctlr->wait.r = 0;
|
ctlr->wait.m = 0;
|
||||||
ctlr->wait.w = 0;
|
ctlr->wait.w = 0;
|
||||||
|
|
||||||
ctlr->ie = Idefmask;
|
ctlr->ie = Idefmask;
|
||||||
|
@ -2197,11 +2192,8 @@ iwlinterrupt(Ureg*, void *arg)
|
||||||
dumpctlr(ctlr);
|
dumpctlr(ctlr);
|
||||||
}
|
}
|
||||||
ctlr->wait.m |= isr;
|
ctlr->wait.m |= isr;
|
||||||
if(ctlr->wait.m & ctlr->wait.w){
|
if(ctlr->wait.m & ctlr->wait.w)
|
||||||
ctlr->wait.r = ctlr->wait.m & ctlr->wait.w;
|
|
||||||
ctlr->wait.m &= ~ctlr->wait.r;
|
|
||||||
wakeup(&ctlr->wait);
|
wakeup(&ctlr->wait);
|
||||||
}
|
|
||||||
done:
|
done:
|
||||||
csr32w(ctlr, Imr, ctlr->ie);
|
csr32w(ctlr, Imr, ctlr->ie);
|
||||||
iunlock(ctlr);
|
iunlock(ctlr);
|
||||||
|
|
|
@ -362,7 +362,9 @@ intrwait(Ctlr *c, u32int mask, int tmo)
|
||||||
{
|
{
|
||||||
u32int status;
|
u32int status;
|
||||||
|
|
||||||
|
ilock(c);
|
||||||
c->waitmsk = Seint | mask;
|
c->waitmsk = Seint | mask;
|
||||||
|
iunlock(c);
|
||||||
do {
|
do {
|
||||||
if(!waserror()){
|
if(!waserror()){
|
||||||
tsleep(&c->r, waitcond, c, 100);
|
tsleep(&c->r, waitcond, c, 100);
|
||||||
|
@ -373,11 +375,10 @@ intrwait(Ctlr *c, u32int mask, int tmo)
|
||||||
break;
|
break;
|
||||||
tmo -= 100;
|
tmo -= 100;
|
||||||
} while(tmo > 0);
|
} while(tmo > 0);
|
||||||
|
|
||||||
ilock(c);
|
ilock(c);
|
||||||
|
c->waitmsk = 0;
|
||||||
status = c->waitsts;
|
status = c->waitsts;
|
||||||
c->waitsts &= ~(status & mask);
|
c->waitsts &= ~(status & mask);
|
||||||
c->waitmsk = 0;
|
|
||||||
if((status & mask) == 0 || (status & Seint) != 0){
|
if((status & mask) == 0 || (status & Seint) != 0){
|
||||||
/* abort command on timeout/error interrupt */
|
/* abort command on timeout/error interrupt */
|
||||||
softreset(c, 0);
|
softreset(c, 0);
|
||||||
|
@ -386,7 +387,7 @@ intrwait(Ctlr *c, u32int mask, int tmo)
|
||||||
}
|
}
|
||||||
iunlock(c);
|
iunlock(c);
|
||||||
|
|
||||||
return status;
|
return status & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue