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 *,