shithub: riscv

Download patch

ref: 5e37e6361c8294da8bc311e626cad3fe781e3e67
parent: 334054e0e7c80a8b6b817089214e5282174fc7c9
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sun Aug 25 14:50:14 EDT 2013

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.

--- a/sys/src/9/pc/etheriwl.c
+++ b/sys/src/9/pc/etheriwl.c
@@ -1990,6 +1990,46 @@
 }
 
 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)
 {
 	FWImage *fw;
@@ -2037,6 +2077,8 @@
 		setoptions(edev);
 
 		ctlr->attached = 1;
+
+		kproc("iwlrecover", iwlrecover, edev);
 	}
 	qunlock(ctlr);
 	poperror();
@@ -2188,7 +2230,7 @@
 		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;
--