From 5e37e6361c8294da8bc311e626cad3fe781e3e67 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 25 Aug 2013 18:50:14 +0200 Subject: [PATCH] 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. --- sys/src/9/pc/etheriwl.c | 44 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/sys/src/9/pc/etheriwl.c b/sys/src/9/pc/etheriwl.c index 72a577166..777de1512 100644 --- a/sys/src/9/pc/etheriwl.c +++ b/sys/src/9/pc/etheriwl.c @@ -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; -- 2.44.0