git: 9front

Download patch

ref: 080efc4f6a7abe034515b7359f5b575a41234742
parent: b03ad851fd46e73742a5f30b2a5803d5b644077e
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;
--