code: plan9front

Download patch

ref: b5655b7247a657bd4b590218a68ed99bbab318f6
parent: 4ec93f94c92eec46433a962eb0f86b6f27909e6c
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Jul 10 05:04:05 EDT 2015

wifi: adjust transmit rate on error (for etheriwl), small mkfile changes

Wnode gets two new counters: txcount and txerror
and actrate pointer that will be between minrate
and maxrate.

driver should use actrate instead of maxrate for
transmission when it can provide error feedback.

when a driver detects a transmission failed, it calls
wifitxfail() with the original packet. wifitxfail() then
reduces wn->actrate.

every 256th packet, we optimistically increase wn->actrate
before transmitting.

--- a/sys/src/9/pc/etheriwl.c
+++ b/sys/src/9/pc/etheriwl.c
@@ -2011,7 +2011,7 @@
 
 		if((w->fc[0] & 0x0c) == 0x08 &&	ctlr->bssnodeid != -1){
 			nodeid = ctlr->bssnodeid;
-			p = wn->maxrate;
+			p = wn->actrate;
 		}
 
 		if(flags & (TFlagNeedRTS|TFlagNeedCTS)){
@@ -2248,6 +2248,8 @@
 	rx = &ctlr->rx;
 	if(ctlr->broken || rx->s == nil || rx->b == nil)
 		return;
+
+	bb = nil;
 	for(hw = get16(rx->s) % Nrx; rx->i != hw; rx->i = (rx->i + 1) % Nrx){
 		uchar type, flags, idx, qid;
 		u32int len;
@@ -2264,14 +2266,15 @@
 		idx = *d++;
 		qid = *d++;
 
+		if(bb != nil){
+			freeb(bb);
+			bb = nil;
+		}
 		if((qid & 0x80) == 0 && qid < nelem(ctlr->tx)){
 			tx = &ctlr->tx[qid];
 			if(tx->n > 0){
 				bb = tx->b[idx];
-				if(bb != nil){
-					tx->b[idx] = nil;
-					freeb(bb);
-				}
+				tx->b[idx] = nil;
 				/* paranoia: clear tx descriptors */
 				dd = tx->d + idx*Tdscsize;
 				cc = tx->c + idx*Tcmdsize;
@@ -2295,6 +2298,14 @@
 		case 24:	/* add node done */
 			break;
 		case 28:	/* tx done */
+			if(ctlr->type == Type4965){
+				if(len <= 20 || d[20] == 1 || d[20] == 2)
+					break;
+			} else {
+				if(len <= 32 || d[32] == 1 || d[32] == 2)
+					break;
+			}
+			wifitxfail(ctlr->wifi, bb);
 			break;
 		case 102:	/* calibration result (Type5000 only) */
 			if(len < 4)
@@ -2351,9 +2362,12 @@
 		case 197:	/* rx compressed ba */
 			break;
 		}
+
 		/* paranoia: clear the descriptor */
 		memset(b->rp, 0, Rdscsize);
 	}
+	if(bb != nil)
+		freeb(bb);
 	csr32w(ctlr, FhRxWptr, ((hw+Nrx-1) % Nrx) & ~7);
 }
 
--- a/sys/src/9/pc/mkfile
+++ b/sys/src/9/pc/mkfile
@@ -124,6 +124,7 @@
 uartaxp.$O:			uartaxp.i
 etherm10g.$O:			etherm10g2k.i etherm10g4k.i
 etheriwl.$O:			wifi.h
+etherwpi.$O:			wifi.h
 etherrt2860.$O: 		wifi.h
 wifi.$O:			wifi.h
 
--- a/sys/src/9/pc/wifi.c
+++ b/sys/src/9/pc/wifi.c
@@ -156,11 +156,18 @@
 	w->seq[0] = seq;
 	w->seq[1] = seq>>8;
 
-	if((w->fc[0] & 0x0c) != 0x00)
+	if((w->fc[0] & 0x0c) != 0x00){
 		b = wifiencrypt(wifi, wn, b);
+		if(b == nil)
+			return;
+	}
 
-	if(b != nil)
-		(*wifi->transmit)(wifi, wn, b);
+	if((wn->txcount++ & 255) == 255){
+		if(wn->actrate != nil && wn->actrate < wn->maxrate)
+			wn->actrate++;
+	}
+
+	(*wifi->transmit)(wifi, wn, b);
 }
 
 static Wnode*
@@ -196,6 +203,23 @@
 	return nn;
 }
 
+void
+wifitxfail(Wifi *wifi, Block *b)
+{
+	Wifipkt *w;
+	Wnode *wn;
+
+	if(b == nil)
+		return;
+	w = (Wifipkt*)b->rp;
+	wn = nodelookup(wifi, w->a1, 0);
+	if(wn == nil)
+		return;
+	wn->txerror++;
+	if(wn->actrate != nil && wn->actrate > wn->minrate)
+		wn->actrate--;
+}
+
 static uchar*
 putrates(uchar *p, uchar *rates)
 {
@@ -417,6 +441,7 @@
 						break;
 					}
 				}
+				wn->actrate = wn->maxrate;
 			}
 			break;
 		case 3:		/* DSPARAMS */
--- a/sys/src/9/pc/wifi.h
+++ b/sys/src/9/pc/wifi.h
@@ -39,7 +39,11 @@
 
 	uchar	*minrate;	/* pointers into wifi->rates */
 	uchar	*maxrate;
+	uchar	*actrate;
 
+	ulong	txcount;	/* statistics for rate adaption */
+	ulong	txerror;
+
 	/* stuff from beacon */
 	int	ival;
 	int	cap;
@@ -87,6 +91,7 @@
 Wifi *wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*));
 void wifiiq(Wifi*, Block*);
 int wifihdrlen(Wifipkt*);
+void wifitxfail(Wifi*, Block*);
 
 long wifistat(Wifi*, void*, long, ulong);
 long wifictl(Wifi*, void*, long);
--- a/sys/src/9/pc64/mkfile
+++ b/sys/src/9/pc64/mkfile
@@ -86,7 +86,7 @@
 PCHEADERS=wifi.h usbehci.h screen.h etherif.h ethermii.h mp.h io.h ahci.h
 
 REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'}
-^($REPCH)\.h:R:	'../pc/\1.h'
+^($REPCH)\.h:R:	../pc/\1.h
 	cp $prereq .
 
 REPCC=`{../port/mkfilelist ../pc}
@@ -122,6 +122,7 @@
 trap.$O:			/sys/include/tos.h
 ethermii.$O:			ethermii.h
 etheriwl.$O:			wifi.h
+etherwpi.$O:			wifi.h
 etherrt2860.$O: 		wifi.h
 wifi.$O:			wifi.h
 
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -69,7 +69,7 @@
 #	etherwavelan	wavelan devi82365 cis pci
 	etheriwl	pci wifi
 	etherwpi	pci wifi
-#	etherrt2860	pci wifi
+	etherrt2860	pci wifi
 	ethervirtio	pci
 	ethermedium
 #	pcmciamodem
--- a/sys/src/9/port/portmkfile
+++ b/sys/src/9/port/portmkfile
@@ -1,9 +1,9 @@
 PORTFILES=`{../port/mkfilelist ../port}
-^($PORTFILES)\.$O:R:	'../port/\1.c'
+^($PORTFILES)\.$O:R:	../port/\1.c
 	$CC $CFLAGS -I. ../port/$stem1.c
 
 IPFILES=`{../port/mkfilelist ../ip}
-^($IPFILES)\.$O:R:	'../ip/\1.c' ../ip/ip.h ../ip/ipv6.h
+^($IPFILES)\.$O:R:	../ip/\1.c ../ip/ip.h ../ip/ipv6.h
 	$CC $CFLAGS -I. ../ip/$stem1.c
 
 %.$O:	%.s