]> git.lizzy.rs Git - plan9front.git/commitdiff
etheriwl: recover from rfkill toggle or firmware crash
authorcinap_lenrek <cinap_lenrek@gmx.de>
Sun, 25 Aug 2013 16:50:14 +0000 (18:50 +0200)
committercinap_lenrek <cinap_lenrek@gmx.de>
Sun, 25 Aug 2013 16:50:14 +0000 (18:50 +0200)
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

index 72a5771665e1d7a70cd93a31c5dec8fca2bd6b7a..777de1512273e0b7b930aa8847bb8b8819f2f1ca 100644 (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;