> Date: Fri, 7 Oct 2016 14:01:27 +0200 > From: Stefan Sperling <s...@stsp.name> > > Imre Vadasz pointed out that rate sets managed by net80211 are sorted > by effective data rate speed, while the iwm_rates array sorts CCK rates > (1 - 11 Mbit/s) before OFDM rates (6Mbit/s - 54Mbit/s). > > rate set (11g): 1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 54 > iwm_rates: 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 54 > > The rate set is sorted at runtime and its length differs between 11a/11b/11g. > So let's add a mapping function and fill the ACK rate bitmap correctly > without making assumptions about the rate set.
Looks good to me. > Index: if_iwm.c > =================================================================== > RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v > retrieving revision 1.143 > diff -u -p -r1.143 if_iwm.c > --- if_iwm.c 5 Oct 2016 18:13:25 -0000 1.143 > +++ if_iwm.c 7 Oct 2016 11:50:19 -0000 > @@ -398,6 +398,7 @@ int iwm_fill_probe_req(struct iwm_softc > int iwm_lmac_scan(struct iwm_softc *); > int iwm_config_umac_scan(struct iwm_softc *); > int iwm_umac_scan(struct iwm_softc *); > +uint8_t iwm_ridx2rate(struct ieee80211_rateset *, int); > void iwm_ack_rates(struct iwm_softc *, struct iwm_node *, int *, int *); > void iwm_mac_ctxt_cmd_common(struct iwm_softc *, struct iwm_node *, > struct iwm_mac_ctx_cmd *, uint32_t, int); > @@ -4881,6 +4882,21 @@ iwm_umac_scan(struct iwm_softc *sc) > return err; > } > > +uint8_t > +iwm_ridx2rate(struct ieee80211_rateset *rs, int ridx) > +{ > + int i; > + uint8_t rval; > + > + for (i = 0; i < rs->rs_nrates; i++) { > + rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL); > + if (rval == iwm_rates[ridx].rate) > + return rs->rs_rates[i]; > + } > + > + return 0; > +} > + > void > iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates, > int *ofdm_rates) > @@ -4895,17 +4911,16 @@ iwm_ack_rates(struct iwm_softc *sc, stru > > if (ni->ni_chan == IEEE80211_CHAN_ANYC || > IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) { > - for (i = 0; i < MIN(IWM_FIRST_OFDM_RATE, rs->rs_nrates); i++) { > - if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0) > + for (i = IWM_FIRST_CCK_RATE; i < IWM_FIRST_OFDM_RATE; i++) { > + if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0) > continue; > cck |= (1 << i); > if (lowest_present_cck > i) > lowest_present_cck = i; > } > } > - for (i = IWM_FIRST_OFDM_RATE; > - i <= MIN(IWM_LAST_NON_HT_RATE, rs->rs_nrates - 1); i++) { > - if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0) > + for (i = IWM_FIRST_OFDM_RATE; i <= IWM_LAST_NON_HT_RATE; i++) { > + if ((iwm_ridx2rate(rs, i) & IEEE80211_RATE_BASIC) == 0) > continue; > ofdm |= (1 << (i - IWM_FIRST_OFDM_RATE)); > if (lowest_present_ofdm > i) > >