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