etheriwl: recover from rfkill toggle or firmware crash

spawn a kernel process to check the broken state of the controller.
if the firmware crashed, or rfkill was toggled we will reset and
reboot the firmware. also power down the card when rfkill is off.
This commit is contained in:
cinap_lenrek 2013-08-25 18:50:14 +02:00
parent 334054e0e7
commit 5e37e6361c

View file

@ -1989,6 +1989,46 @@ iwlpromiscuous(void *arg, int on)
qunlock(ctlr);
}
static void
iwlrecover(void *arg)
{
Ether *edev;
Ctlr *ctlr;
edev = arg;
ctlr = edev->ctlr;
for(;;){
while(waserror())
;
tsleep(&up->sleep, return0, 0, 4000);
poperror();
qlock(ctlr);
for(;;){
if(ctlr->broken == 0)
break;
if(ctlr->power)
poweroff(ctlr);
if((csr32r(ctlr, Gpc) & RfKill) == 0)
break;
if(reset(ctlr) != nil)
break;
if(boot(ctlr) != nil)
break;
ctlr->bcastnodeid = -1;
ctlr->bssnodeid = -1;
ctlr->aid = 0;
rxon(edev, ctlr->wifi->bss);
break;
}
qunlock(ctlr);
}
}
static void
iwlattach(Ether *edev)
{
@ -2037,6 +2077,8 @@ iwlattach(Ether *edev)
setoptions(edev);
ctlr->attached = 1;
kproc("iwlrecover", iwlrecover, edev);
}
qunlock(ctlr);
poperror();
@ -2188,7 +2230,7 @@ iwlinterrupt(Ureg*, void *arg)
receive(ctlr);
if(isr & Ierr){
ctlr->broken = 1;
iprint("#l%d: fatal firmware error\n", edev->ctlrno);
print("#l%d: fatal firmware error\n", edev->ctlrno);
dumpctlr(ctlr);
}
ctlr->wait.m |= isr;