ref: 2009d55643b87d6d0618c2fcfce5c440147138eb
parent: ac52599eef2ab79a64c30a8046a51b62501ca9ab
author: cinap_lenrek <[email protected]>
date: Fri Jul 26 00:37:32 EDT 2013
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.
--- a/sys/src/9/pc/ether82563.c
+++ b/sys/src/9/pc/ether82563.c
@@ -1053,7 +1053,9 @@
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;
}
--- a/sys/src/9/pc/etheriwl.c
+++ b/sys/src/9/pc/etheriwl.c
@@ -349,7 +349,6 @@
Rendez;
u32int m;
u32int w;
- u32int r;
} wait;
struct {
@@ -1014,39 +1013,35 @@
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 @@
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 @@
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);
--- a/sys/src/9/pc/pmmc.c
+++ b/sys/src/9/pc/pmmc.c
@@ -362,7 +362,9 @@
{
u32int status;
+ ilock(c);
c->waitmsk = Seint | mask;
+ iunlock(c);
do {
if(!waserror()){
tsleep(&c->r, waitcond, c, 100);
@@ -373,11 +375,10 @@
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 @@
}
iunlock(c);
- return status;
+ return status & mask;
}