This cleans up the code which handles EDCA parameters in rtwn/urtwn. The driver now gets its EDCA params from net80211 instead of hardcoding them. There's a bit of a layer violation since the driver writes to ic->ic_edca_ac because net80211 does not fill it in yet. I think net80211 should do that, but this can be fixed later on.
Enable hardware management of EDCA AC queues. Not sure if this brings any benefit but this is worth trying and does not cause harm in my testing. Handling of frame collisions with EDCA involves random backoffs. I found a register that looks like a seed for the pseudo-RNG involved in computing backoffs. After a cold boot (or hotplug in case of USB) this register always has the value 0x11e21051 on all my devices. The register can be written and will retain its most recent value until the next reboot/hotplug. Feed it with arc4random() during initialization. Linux does not do anything with this register unfortunately so it is hard to know if this really does anything. The magic value 0x11e21051 does not show up in Linux rtlwifi sources. Add a comment to hint at the meaning of numbers written to SIFS registers, and rename some SIFS registers to better names found in Linux. For some bizarre reason Linux is using a mix of both the old and new register names seen in this diff. (SIFS means "short interface space", the time period within which important frames such as ACKs may be sent when the medium becomes available after the previous frame was transmitted). Tested on: 8188CE (PCI) 8192CU (USB) 8188EU (USB) 8188CUS (USB) Index: ic/r92creg.h =================================================================== RCS file: /cvs/src/sys/dev/ic/r92creg.h,v retrieving revision 1.4 diff -u -p -r1.4 r92creg.h --- ic/r92creg.h 8 Jan 2017 05:48:27 -0000 1.4 +++ ic/r92creg.h 30 Jan 2017 19:07:38 -0000 @@ -218,8 +218,8 @@ #define R92C_BSSID 0x618 #define R92C_MAR 0x620 #define R92C_MAC_SPEC_SIFS 0x63a -#define R92C_R2T_SIFS 0x63c -#define R92C_T2T_SIFS 0x63e +#define R92C_RESP_SIFS_CCK 0x63c +#define R92C_RESP_SIFS_OFDM 0x63e #define R92C_ACKTO 0x640 #define R92C_CAMCMD 0x670 #define R92C_CAMWRITE 0x674 @@ -505,6 +505,15 @@ #define R92C_EDCA_PARAM_ECWMAX_S 12 #define R92C_EDCA_PARAM_TXOP_M 0xffff0000 #define R92C_EDCA_PARAM_TXOP_S 16 + +/* Bits for R92C_ACMHWCTRL */ +#define R92C_ACMHW_HWEN 0x01 +#define R92C_ACMHW_BEQEN 0x02 +#define R92C_ACMHW_VIQEN 0x04 +#define R92C_ACMHW_VOQEN 0x08 +#define R92C_ACMHW_BEQSTATUS 0x10 +#define R92C_ACMHW_VIQSTATUS 0x20 +#define R92C_ACMHW_VOQSTATUS 0x40 /* Bits for R92C_TXPAUSE. */ #define R92C_TXPAUSE_AC_VO 0x01 Index: ic/rtwn.c =================================================================== RCS file: /cvs/src/sys/dev/ic/rtwn.c,v retrieving revision 1.14 diff -u -p -r1.14 rtwn.c --- ic/rtwn.c 30 Jan 2017 17:48:26 -0000 1.14 +++ ic/rtwn.c 30 Jan 2017 19:50:55 -0000 @@ -903,10 +903,7 @@ rtwn_newstate(struct ieee80211com *ic, e R92C_BCN_CTRL_DIS_TSF_UDT0); /* Reset EDCA parameters. */ - rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3217); - rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4317); - rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x00105320); - rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a444); + rtwn_edca_init(sc); rtwn_updateslot(ic); rtwn_update_short_preamble(ic); @@ -1012,15 +1009,9 @@ rtwn_newstate(struct ieee80211com *ic, e /* Enable TSF synchronization. */ rtwn_tsf_sync_enable(sc); - rtwn_write_1(sc, R92C_SIFS_CCK + 1, 10); - rtwn_write_1(sc, R92C_SIFS_OFDM + 1, 10); - rtwn_write_1(sc, R92C_SPEC_SIFS + 1, 10); - rtwn_write_1(sc, R92C_MAC_SPEC_SIFS + 1, 10); - rtwn_write_1(sc, R92C_R2T_SIFS + 1, 10); - rtwn_write_1(sc, R92C_T2T_SIFS + 1, 10); - /* Intialize rate adaptation. */ rtwn_ra_init(sc); + /* Turn link LED on. */ rtwn_set_led(sc, RTWN_LED_LINK, 1); @@ -1080,12 +1071,15 @@ rtwn_updateedca(struct ieee80211com *ic) struct ieee80211_edca_ac_params *ac; int s, aci, aifs, slottime; + if (ic->ic_flags & IEEE80211_F_SHSLOT) + slottime = 9; /* XXX needs a macro in ieee80211.h */ + else + slottime = IEEE80211_DUR_DS_SLOT; s = splnet(); - slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; for (aci = 0; aci < EDCA_NUM_AC; aci++) { ac = &ic->ic_edca_ac[aci]; /* AIFS[AC] = AIFSN[AC] * aSlotTime + aSIFSTime. */ - aifs = ac->ac_aifsn * slottime + 10; + aifs = ac->ac_aifsn * slottime + IEEE80211_DUR_DS_SIFS; rtwn_write_4(sc, aci2reg[aci], SM(R92C_EDCA_PARAM_TXOP, ac->ac_txoplimit) | SM(R92C_EDCA_PARAM_ECWMIN, ac->ac_ecwmin) | @@ -1710,26 +1704,33 @@ rtwn_rxfilter_init(struct rtwn_softc *sc void rtwn_edca_init(struct rtwn_softc *sc) { - /* XXX Use the same values for PCI and USB? */ - if (sc->chip & RTWN_CHIP_PCI) { - rtwn_write_2(sc, R92C_SPEC_SIFS, 0x1010); - rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x1010); - rtwn_write_2(sc, R92C_SIFS_CCK, 0x1010); - rtwn_write_2(sc, R92C_SIFS_OFDM, 0x0e0e); - rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b); - rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f); - rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4322); - rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3222); - } else if (sc->chip & RTWN_CHIP_USB) { - rtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a); - rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a); - rtwn_write_2(sc, R92C_SIFS_CCK, 0x100a); - rtwn_write_2(sc, R92C_SIFS_OFDM, 0x100a); - rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b); - rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f); - rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005ea324); - rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002fa226); - } + struct ieee80211com *ic = &sc->sc_ic; + int mode, aci; + + /* Set SIFS; 0x10 = 16 usec (SIFS 11g), 0x0a = 10 usec (SIFS 11b) */ + rtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a); + rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a); + rtwn_write_2(sc, R92C_SIFS_CCK, 0x100a); + rtwn_write_2(sc, R92C_SIFS_OFDM, 0x100a); + rtwn_write_2(sc, R92C_RESP_SIFS_CCK, 0x100a); + rtwn_write_2(sc, R92C_RESP_SIFS_OFDM, 0x100a); + + if (ic->ic_curmode == IEEE80211_MODE_AUTO) + mode = IEEE80211_MODE_11G; /* XXX */ + else + mode = ic->ic_curmode; + for (aci = 0; aci < EDCA_NUM_AC; aci++) + memcpy(&ic->ic_edca_ac[aci], &ieee80211_edca_table[mode][aci], + sizeof(struct ieee80211_edca_ac_params)); + rtwn_updateedca(ic); + + rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x086666); /* linux magic */ + + rtwn_write_4(sc, R92C_EDCA_RANDOM_GEN, arc4random()); + + /* Enable hardware AC queue management. */ + rtwn_write_1(sc, R92C_ACMHWCTRL, R92C_ACMHW_HWEN | R92C_ACMHW_BEQEN | + R92C_ACMHW_VIQEN | R92C_ACMHW_VOQEN); } void