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

Reply via email to