In my latest commit I enabled "hardware AC queue management" in rtwn.

Upon closer investigation, this register works differently. It needs to
reflect "ACM" (admission control mandatory) flags which the AP sends to
clients in EDCA parameters.

There is one such flag per traffic class, and the lowest class never sets it.
If the flag is set for a traffic class, clients can ask the AP for some
exlusively reserved bandwidth (actually, air time) within this traffic class.
Which is why all this stuff falls into the area of quality of service (QOS).
The basic idea is that, during periods of contention for the medium, frames
in higher traffic classes are sent before frames in lower classes.

ieee80211_parse_edca_params_body() stores this flag in ac->ac_acm.
Our sets of default EDCA parameters do not set these flags, so with
an OpenBSD AP the flags will never be set.

See also ieee80211_up_to_ac() in ieee80211_output.c which looks at this
bit in a different context. It avoids sending in a traffic class which
requires admission and falls back to one that does not.

Anyway, it is better to actually tell the hardware what's going on
rather than always setting these bits.

Index: rtwn.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/rtwn.c,v
retrieving revision 1.16
diff -u -p -r1.16 rtwn.c
--- rtwn.c      31 Jan 2017 09:21:46 -0000      1.16
+++ rtwn.c      31 Jan 2017 09:47:38 -0000
@@ -1068,6 +1068,7 @@ rtwn_updateedca(struct ieee80211com *ic)
        };
        struct ieee80211_edca_ac_params *ac;
        int s, aci, aifs, slottime;
+       uint8_t acm = 0;
 
        if (ic->ic_flags & IEEE80211_F_SHSLOT)
                slottime = 9; /* XXX needs a macro in ieee80211.h */
@@ -1083,8 +1084,28 @@ rtwn_updateedca(struct ieee80211com *ic)
                    SM(R92C_EDCA_PARAM_ECWMIN, ac->ac_ecwmin) |
                    SM(R92C_EDCA_PARAM_ECWMAX, ac->ac_ecwmax) |
                    SM(R92C_EDCA_PARAM_AIFS, aifs));
+
+               /* Is admission control mandatory for this queue? */
+               if (ac->ac_acm) {
+                       switch (aci) {
+                       case EDCA_AC_BE:
+                               acm |= R92C_ACMHW_BEQEN;
+                               break;
+                       case EDCA_AC_VI:
+                               acm |= R92C_ACMHW_VIQEN;
+                               break;
+                       case EDCA_AC_VO:
+                               acm |= R92C_ACMHW_VOQEN;
+                               break;
+                       default:
+                               break;
+                       }
+               }
        }
        splx(s);
+
+       /* Enable hardware admission control. */
+       rtwn_write_1(sc, R92C_ACMHWCTRL, R92C_ACMHW_HWEN | acm);
 }
 
 int
@@ -1725,10 +1746,6 @@ rtwn_edca_init(struct rtwn_softc *sc)
        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