On Tue, May 30, 2017 at 11:03:09AM +0200, Stefan Sperling wrote:
> ok?

Always wait for the second diff!

In the previous version I missed an indirection via wn->ridx[].
wrong: rinfo = &iwn_rates[ieee80211_min_basic_rate(ic)]
correct: rinfo = &iwn_rates[wn->ridx[ieee80211_min_basic_rate(ic)]];

Because of this I found that we have to hardcode the rate of the
broadcast node added to firmware, because wn->ridx is not set up
until we associate. Still works, anyway. Seems the basic rate
specified in the Tx command is all that matters.

Index: dev/pci/if_iwn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.186
diff -u -p -r1.186 if_iwn.c
--- dev/pci/if_iwn.c    26 Apr 2017 07:53:17 -0000      1.186
+++ dev/pci/if_iwn.c    30 May 2017 09:19:06 -0000
@@ -2896,8 +2896,7 @@ iwn_tx(struct iwn_softc *sc, struct mbuf
        /* Choose a TX rate index. */
        if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
            type != IEEE80211_FC0_TYPE_DATA)
-               ridx = (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) ?
-                   IWN_RIDX_OFDM6 : IWN_RIDX_CCK1;
+               ridx = wn->ridx[ieee80211_max_basic_rate(ic)];
        else if (ic->ic_fixed_mcs != -1)
                ridx = sc->fixed_ridx;
        else if (ic->ic_fixed_rate != -1)
@@ -3430,6 +3429,7 @@ iwn5000_add_node(struct iwn_softc *sc, s
 int
 iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni)
 {
+       struct ieee80211com *ic = &sc->sc_ic;
        struct iwn_node *wn = (void *)ni;
        struct ieee80211_rateset *rs = &ni->ni_rates;
        struct iwn_cmd_link_quality linkq;
@@ -3466,11 +3466,8 @@ iwn_set_link_quality(struct iwn_softc *s
                                break;
                }
 
-               /* Fill the rest with the lowest legacy rate. */
-               if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan))
-                       rinfo = &iwn_rates[IWN_RIDX_OFDM6];
-               else
-                       rinfo = &iwn_rates[IWN_RIDX_CCK1];
+               /* Fill the rest with the lowest basic rate. */
+               rinfo = &iwn_rates[wn->ridx[ieee80211_min_basic_rate(ic)]];
                while (i < IWN_MAX_TX_RETRIES) {
                        linkq.retry[i].plcp = rinfo->plcp;
                        linkq.retry[i].rflags = rinfo->flags;
Index: net80211/ieee80211.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211.c,v
retrieving revision 1.58
diff -u -p -r1.58 ieee80211.c
--- net80211/ieee80211.c        13 Jan 2016 14:33:07 -0000      1.58
+++ net80211/ieee80211.c        30 May 2017 08:38:14 -0000
@@ -712,6 +712,43 @@ ieee80211_setbasicrates(struct ieee80211
        }
 }
 
+int
+ieee80211_min_basic_rate(struct ieee80211com *ic)
+{
+       struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
+       int i;
+
+       for (i = 0; i < rs->rs_nrates; i++) {
+               if (rs->rs_rates[i] & IEEE80211_RATE_BASIC)
+                       return i;
+       }
+
+       return 0;
+}
+
+int
+ieee80211_max_basic_rate(struct ieee80211com *ic)
+{
+       struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
+       int i, best, rval, best_rval;
+
+       /* Defaults to 1 Mbit/s on 2GHz and 6 Mbit/s on 5GHz. */
+       best = 0;
+       best_rval = (rs->rs_rates[best] & IEEE80211_RATE_VAL);
+
+       for (i = 0; i < rs->rs_nrates; i++) {
+               if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)
+                       continue;
+               rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);
+               if (rval > best_rval) {
+                       best_rval = rval;
+                       best = i;
+               }
+       }
+
+       return best;
+}
+
 /*
  * Set the current phy mode and recalculate the active channel
  * set based on the available channels for this mode.  Also
Index: net80211/ieee80211_var.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_var.h,v
retrieving revision 1.77
diff -u -p -r1.77 ieee80211_var.h
--- net80211/ieee80211_var.h    2 Feb 2017 16:47:53 -0000       1.77
+++ net80211/ieee80211_var.h    30 May 2017 08:28:46 -0000
@@ -402,6 +402,8 @@ u_int       ieee80211_mhz2ieee(u_int, u_int);
 u_int  ieee80211_chan2ieee(struct ieee80211com *,
                const struct ieee80211_channel *);
 u_int  ieee80211_ieee2mhz(u_int, u_int);
+int    ieee80211_min_basic_rate(struct ieee80211com *);
+int    ieee80211_max_basic_rate(struct ieee80211com *);
 int    ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
 enum ieee80211_phymode ieee80211_next_mode(struct ifnet *);
 enum ieee80211_phymode ieee80211_chan2mode(struct ieee80211com *,

Reply via email to