ref: c5c79d61e67f2c74a8d57eb1aeea87a23eeadd87
parent: 2367a2aeaec8432e6b059135e49c2fa86e415ae5
author: kemal <kemalinanc8@gmail.com>
date: Sat Aug 21 18:23:12 EDT 2021
etheriwl: fixes for 7260 ac 2021-08-14 17:50 GMT, kemal <kemalinanc8@gmail.com>: > 1- as driver reads 8 bytes from nvm instead of 6 so fw doesn't > spit us an ADVANCED_SYSASSERT, it was reading 2 more > extra bytes. apparently those 2 extra bytes were put to > the first 2 bytes of our buffer, so we got to skip that. some more thoughts on this, i think as 0x15*2 is not multiple of 8, fw rounds the offset to 0x14*2. i have touched to code to read data from 0x14*2 then ignore the first 2 bytes, just so it's not confusing. if this causes mac to be read wrong again, report. also, some more changes: 1. set the fwname at iwlpci, just to align the behavior with 8000+. this is a cosmetic change. 2. i have discovered that on device boot/reset/shutdown functions, our driver slept way much more than it should. the reason for that is, driver used the function delay() on places where it needs to use microdelay() instead. i have modified the code to use microdelay(). wpi likely needs similar changes too. i hope that this does not break the code. 3. zzz a bit more on tx/rx scheduler shutdowns and niclock. 4. openbsd's iwm and linux apparently does not check if ownership was obtained anymore in their handover functions. instead they just loop until the hw is ready. aligned the behavior. see linux commit: 289e5501c3141191dd830957f1d764d3dc14a54f 5. don't take antenna masks from nvm. it's apparently empty in some cards from 7k family. we will rely on what the fw file gives us. 6. when the calibration is completed, wakeup the proc that runs postboot. otherwise that thing sleeps for like 2 whole seconds even if calibration completed earlier. i honestly don't think any of these changes will fix 7260 not being able to get calibration results, but i don't see anything wrong at all in postboot7000 at this point. i will just hope these changes somehow make it get calibration results. NOTE: latest patch on the 9front ml, posted Mon, 14 Feb 2022 15:26:55 +0300 (non functional as of yet)
--- a/sys/src/9/pc/etheriwl.c
+++ b/sys/src/9/pc/etheriwl.c
@@ -329,7 +329,29 @@
SchedTransTblOff = 0x7E0, // +q*2
};
+/*
+ * uCode TLV api
+ */
enum {
+ /* api[0] */
+ UcodeApiSta = 1<<30,
+};
+
+/*
+ * uCode capabilities
+ */
+enum {
+ /* capa[0] */
+ UcodeCapLar = 1<<1,
+
+ /* capa[1] */
+ UcodeCapQuota = 1<<12,
+
+ /* capa[2] */
+ UcodeCapLar2 = 1<<9,
+};
+
+enum {
FilterPromisc = 1<<0,
FilterCtl = 1<<1,
FilterMulticast = 1<<2,
@@ -418,6 +440,7 @@
uint build;
char descr[64+1];
+ u32int flags;
u32int capa[4];
u32int api[4];
@@ -635,8 +658,7 @@
Type2030 = 12,
Type2000 = 16,
- Type7260 = 30,
- Type8265 = 35,
+ Type7260 = 20,
};
static struct ratetab {
@@ -690,7 +712,6 @@
[Type6005] "iwn-6005", /* see in iwlattach() below */
[Type2030] "iwn-2030",
[Type2000] "iwn-2000",
- [Type7260] "iwm-7260-17",
};
static char *qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block);
@@ -728,10 +749,12 @@
int i;
csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) | MacAccessReq);
- for(i=0; i<1000; i++){
+ if(ctlr->family >= 8000)
+ microdelay(2);
+ for(i=0; i<1500; i++){
if((csr32r(ctlr, Gpc) & (NicSleep | MacAccessEna)) == MacAccessEna)
return 0;
- delay(10);
+ microdelay(10);
}
return "niclock: timeout";
}
@@ -944,7 +967,7 @@
for(j=0; j<100; j++){
if(csr32r(ctlr, Cfg) & EepromLocked)
return 0;
- delay(10);
+ microdelay(10);
}
}
return "eepromlock: timeout";
@@ -969,7 +992,7 @@
w = csr32r(ctlr, EepromIo);
if(w & 1)
break;
- delay(5);
+ microdelay(5);
}
if(i == 10)
return "eepromread: timeout";
@@ -990,14 +1013,15 @@
static char*
handover(Ctlr *ctlr)
{
- int i;
+ int i, j;
csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
for(i=0; i<5; i++){
if(csr32r(ctlr, Cfg) & NicReady)
goto Ready;
- delay(10);
+ microdelay(10);
}
+
if(ctlr->family >= 7000){
csr32w(ctlr, Dbglinkpwrmgmt, csr32r(ctlr, Dbglinkpwrmgmt) | (1<<31));
delay(1);
@@ -1004,20 +1028,16 @@
}
csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | Prepare);
- for(i=0; i<15000; i++){
- if((csr32r(ctlr, Cfg) & PrepareDone) == 0)
- break;
- delay(10);
+ for(i=0; i<750; i++){
+ csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
+ for(j=0; j<5; j++){
+ if(csr32r(ctlr, Cfg) & NicReady)
+ goto Ready;
+ microdelay(10);
+ }
+ microdelay(200);
}
- if(i >= 15000)
- return "handover: timeout";
- csr32w(ctlr, Cfg, csr32r(ctlr, Cfg) | NicReady);
- for(i=0; i<5; i++){
- if(csr32r(ctlr, Cfg) & NicReady)
- goto Ready;
- delay(10);
- }
return "handover: timeout";
Ready:
if(ctlr->family >= 7000)
@@ -1035,7 +1055,7 @@
for(i=0; i<2500; i++){
if(csr32r(ctlr, Gpc) & MacClockReady)
return 0;
- delay(10);
+ microdelay(10);
}
return "clockwait: timeout";
}
@@ -1046,7 +1066,6 @@
int capoff;
char *err;
-
if(ctlr->family >= 7000){
/* Reset entire device */
csr32w(ctlr, Reset, (1<<7));
@@ -1100,7 +1119,7 @@
prphread(ctlr, OscClk);
prphread(ctlr, OscClk);
- delay(20);
+ microdelay(20);
prphwrite(ctlr, OscClk, prphread(ctlr, OscClk) | OscClkCtrl);
@@ -1119,7 +1138,7 @@
prphwrite(ctlr, ApmgClkEna, DmaClkRqt | BsmClkRqt);
else
prphwrite(ctlr, ApmgClkEna, DmaClkRqt);
- delay(20);
+ microdelay(20);
/* Disable L1-Active. */
prphwrite(ctlr, ApmgPciStt, prphread(ctlr, ApmgPciStt) | (1<<11));
@@ -1158,7 +1177,7 @@
for(j = 0; j < 200; j++){
if(csr32r(ctlr, FhTxStatus) & (0x10000<<i))
break;
- delay(10);
+ microdelay(20);
}
}
nicunlock(ctlr);
@@ -1168,17 +1187,17 @@
if(niclock(ctlr) == nil){
if(ctlr->mqrx){
prphwrite(ctlr, RfhDmaCfg, 0);
- for(j = 0; j < 200; j++){
+ for(j = 0; j < 1000; j++){
if(prphread(ctlr, RfhGenStatus) & RfhGenStatusDmaIdle)
break;
- delay(10);
+ microdelay(10);
}
} else {
csr32w(ctlr, FhRxConfig, 0);
- for(j = 0; j < 200; j++){
+ for(j = 0; j < 1000; j++){
if(csr32r(ctlr, FhRxStatus) & 0x1000000)
break;
- delay(10);
+ microdelay(10);
}
}
nicunlock(ctlr);
@@ -1190,7 +1209,7 @@
prphwrite(ctlr, ApmgClkDis, DmaClkRqt);
nicunlock(ctlr);
}
- delay(5);
+ microdelay(5);
}
if(ctlr->family >= 7000){
@@ -1206,12 +1225,12 @@
for(j = 0; j < 100; j++){
if(csr32r(ctlr, Reset) & (1<<8))
break;
- delay(10);
+ microdelay(10);
}
/* Reset the entire device. */
csr32w(ctlr, Reset, csr32r(ctlr, Reset) | (1<<7));
- delay(10);
+ delay(5);
/* Clear "initialization complete" bit. */
csr32w(ctlr, Gpc, csr32r(ctlr, Gpc) & ~InitDone);
@@ -1239,7 +1258,7 @@
if((err = niclock(ctlr)) != nil)
return err;
prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) | ResetReq);
- delay(5);
+ microdelay(5);
prphwrite(ctlr, ApmgPs, prphread(ctlr, ApmgPs) & ~ResetReq);
nicunlock(ctlr);
@@ -1308,7 +1327,7 @@
ctlr->type &= 0x1FF;
ctlr->dash = ctlr->type & 3, ctlr->type >>= 2;
ctlr->step = ctlr->type & 3, ctlr->type >>= 2;
- if(fwname[ctlr->type] == nil){
+ if(ctlr->fwname == nil && fwname[ctlr->type] == nil){
print("iwl: unsupported controller type %d\n", ctlr->type);
return -1;
}
@@ -1478,6 +1497,11 @@
s = &i->boot.text;
s->addr = 0x00000000;
goto Sect;
+ case 18:
+ if(l < 4)
+ goto Tooshort;
+ i->flags = get32(p);
+ break;
case 19:
if(i->main.nsect >= nelem(i->main.sect))
return "too many main sections";
@@ -1984,7 +2008,7 @@
*p++ = mcc[0];
*p++ = 0;
*p++ = 0; // reserved
- if(1){
+ if(ctlr->fw->capa[2] & UcodeCapLar2){
p += 4;
p += 5*4;
}
@@ -2236,10 +2260,6 @@
ctlr->rfcfg.step = (u >> 2) & 3;
ctlr->rfcfg.dash = (u >> 0) & 3;
ctlr->rfcfg.pnum = (u >> 6) & 3;
-
- ctlr->rfcfg.txantmask = (u >> 8) & 15;
- ctlr->rfcfg.rxantmask = (u >> 12) & 15;
-
} else {
if(readnvmsect(ctlr, 12, buf, 8, 0) != 8)
return "can't read nvm phy config";
@@ -2272,7 +2292,20 @@
ea[5] = a1 >> 0;
}
} else {
- readnvmsect(ctlr, 0, ea, Eaddrlen, 0x15<<1);
+ /*
+ * 7260 gets angry if we read 6 bytes from 0x15*2.
+ * reading 8 bytes from 0x14*2 works fine.
+ */
+ if(readnvmsect(ctlr, 0, buf, 8, 0x14<<1) != 8)
+ return "can't read ea from nvm";
+
+ /* byte order is 16 bit little endian. */
+ ea[0] = buf[3];
+ ea[1] = buf[2];
+ ea[2] = buf[5];
+ ea[3] = buf[4];
+ ea[4] = buf[7];
+ ea[5] = buf[6];
}
memmove(ctlr->edev->addr, ea, Eaddrlen);
@@ -2366,7 +2399,7 @@
p += 2; /* sleep_tx_count */
p++; /* sleep state flags */
- *p++ = (ctlr->fw->api[0] & (1<<30)) != 0 ? type : 0; /* station_type */
+ *p++ = ctlr->fw->api[0] & UcodeApiSta ? type : 0; /* station_type */
p += 2; /* assoc id */
@@ -2375,7 +2408,7 @@
put32(p, 1<<0);
p += 4; /* tfd_queue_mask */
- if(1){
+ if(ctlr->fw->api[0] & UcodeApiSta){
p += 2; /* rx_ba_window */
p++; /* sp_length */
p++; /* uapsd_acs */
@@ -2640,7 +2673,7 @@
static char*
settimeevent(Ctlr *ctlr, int amr, int ival)
{
- int duration, delay, timeid;
+ int timeid;
uchar c[9*4], *p;
char *err;
@@ -2662,14 +2695,6 @@
break;
}
- if(ival){
- duration = ival*2;
- delay = ival/2;
- } else {
- duration = 1024;
- delay = 0;
- }
-
memset(p = c, 0, sizeof(c));
put32(p, ctlr->macid);
p += 4;
@@ -2678,23 +2703,27 @@
put32(p, timeid);
p += 4;
- put32(p, 0); // apply time
- p += 4;
- put32(p, delay);
- p += 4;
- put32(p, 0); // depends on
- p += 4;
- put32(p, 1); // interval
- p += 4;
- put32(p, duration);
- p += 4;
- *p++ = 1; // repeat
- *p++ = 0; // max frags
- put16(p, 1<<0 | 1<<1 | 1<<11); // policy
- p += 2;
+ if(amr == CmdRemove)
+ p += 6*4;
+ else{
+ put32(p, 0); // apply time
+ p += 4;
+ put32(p, ival/2); // max delay
+ p += 4;
+ put32(p, 0); // depends on
+ p += 4;
+ put32(p, 1); // interval
+ p += 4;
+ put32(p, ival? ival*2: 1024); // duration
+ p += 4;
+ *p++ = 1; // repeat
+ *p++ = 0; // max frags
+ put16(p, 1<<0 | 1<<1 | 1<<11); // policy
+ p += 2;
+ }
ctlr->te.active = 0;
- if((err = cmd(ctlr, 41, c, p - c)) != nil)
+ if((err = cmd(ctlr, 41, c, p - c)) != nil)
return err;
if(amr == CmdRemove){
@@ -2713,6 +2742,9 @@
uchar c[4*(3*4)], *p;
int i;
+ if((ctlr->fw->capa[1] & UcodeCapQuota) == 0)
+ return nil;
+
i = 0;
p = c;
@@ -2822,13 +2854,13 @@
return cmd(ctlr, 210, c, 11*4);
}
-static void
+static char*
tttxbackoff(Ctlr *ctlr)
{
uchar c[4];
put32(c, 0);
- cmd(ctlr, 126, c, sizeof(c));
+ return cmd(ctlr, 126, c, sizeof(c));
}
static char*
@@ -2848,6 +2880,9 @@
char *err;
if(ctlr->calib.done == 0){
+ if(ctlr->family == 7000)
+ if((err = sendbtcoexadv(ctlr)) != nil)
+ return err;
if((err = readnvmconfig(ctlr)) != nil)
return err;
}
@@ -2897,16 +2932,16 @@
/* Initialize tx backoffs to the minimum. */
if(ctlr->family == 7000)
- tttxbackoff(ctlr);
+ if((err = tttxbackoff(ctlr)) != nil)
+ return err;
if((err = updatedevicepower(ctlr)) != nil){
print("can't update device power: %s\n", err);
return err;
}
- if((err = sendmccupdate(ctlr, "ZZ")) != nil){
- print("can't disable beacon filter: %s\n", err);
- return err;
- }
+ if(ctlr->fw->capa[0] & UcodeCapLar)
+ if((err = sendmccupdate(ctlr, "ZZ")) != nil)
+ return err;
if((err = disablebeaconfilter(ctlr)) != nil){
print("can't disable beacon filter: %s\n", err);
return err;
@@ -3362,7 +3397,7 @@
for(i=0; i<1000; i++){
if((prphread(ctlr, BsmWrCtrl) & (1<<31)) == 0)
break;
- delay(10);
+ microdelay(10);
}
if(i == 1000){
nicunlock(ctlr);
@@ -3418,6 +3453,7 @@
static char*
qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
{
+ char *err;
int hdrlen;
Block *bcmd;
uchar *d, *c;
@@ -3452,10 +3488,10 @@
return "qcmd: broken";
}
/* wake up the nic (just needed for 7k) */
- if(ctlr->family == 7000 && q->n == 0)
- if(niclock(ctlr) != nil){
+ if(ctlr->family == 7000 && qid == 4 && q->n == 0)
+ if((err = niclock(ctlr)) != nil){
iunlock(ctlr);
- return "qcmd: busy";
+ return err;
}
q->n++;
q->lastcmd = code;
@@ -3586,9 +3622,16 @@
int i;
for(i = 0; i < nelem(ctlr->tx); i++)
- flushq(ctlr, i);
- settimeevent(ctlr, CmdRemove, 0);
+ if((err = flushq(ctlr, i)) != nil){
+ print("can't flush queue %d: %s\n", i, err);
+ return err;
+ }
+ if((err = settimeevent(ctlr, CmdRemove, 0)) != nil){
+ print("can't remove time event: %s\n", err);
+ return err;
+ }
+
if((err = setbindingquotas(ctlr, -1)) != nil){
print("can't disable quotas: %s\n", err);
return err;
@@ -3630,7 +3673,7 @@
return err;
}
if((err = setbindingcontext(ctlr, CmdAdd)) != nil){
- print("removing bindingcontext: %s\n", err);
+ print("adding bindingcontext: %s\n", err);
return err;
}
if((err = setmcastfilter(ctlr)) != nil){
@@ -4176,6 +4219,8 @@
/* wet floor */
case 103: /* calibration done (Type5000 only) */
ctlr->calib.done = 1;
+ if(ctlr->wait.w == Ierr)
+ wakeup(&ctlr->wait);
break;
case 107: /* calibration result (>= 7000 family) */
if(ctlr->family < 7000)
@@ -4283,8 +4328,8 @@
if(tx != nil && tx->n > 0){
tx->n--;
wakeup(tx);
- /* unlock 7k family nics as all commands are done */
- if(ctlr->family == 7000 && tx->n == 0)
+ /* unlock 7k family nics as the command is done */
+ if(ctlr->family == 7000 && qid == 4 && tx->n == 0)
nicunlock(ctlr);
}
}
@@ -4354,14 +4399,12 @@
int family;
pdev = nil;
- while(pdev = pcimatch(pdev, 0, 0)) {
+ while(pdev = pcimatch(pdev, Vintel, 0)) {
Ctlr *ctlr;
void *mem;
if(pdev->ccrb != 2 || pdev->ccru != 0x80)
continue;
- if(pdev->vid != 0x8086)
- continue;
if(pdev->mem[0].bar & 1)
continue;
@@ -4399,7 +4442,7 @@
case 0x08b1: /* Wireless AC 7260 */
case 0x08b2: /* Wireless AC 7260 */
family = 7000;
- fwname = nil;
+ fwname = "iwm-7260-17";
break;
case 0x24f3: /* Wireless AC 8260 */
family = 8000;