> Date: Tue, 5 Jan 2016 15:06:00 +0100
> From: Stefan Sperling <[email protected]>
>
> iwm adjusts the firmware's Tx rate retry table dynamically such
> that the first slot in this table always reflects the current
> rate chosen by AMRR.
> The table starts off looking like this:
>
> 0 1 n-2 n-1 n
> MCS 0, MCS 0, ..., MCS 0, CCK 2, CCK 1
>
> (On 5GHz, the lowest rate is OFDM 6 rather than CCK 1.)
>
> As AMRR raises the desired Tx rate to say, MCS 4, we fill in
> the higher rates at the front:
>
> 0 1 n-2 n-1 n
> MCS 4, MCS 3, ..., MCS 1, MCS 0, CCK 2
>
> However, the code calculating the first slot the firmware shall
> use when sending a data frame still assumes a static layout and
> points the firmware at slot number 'n - 1 - r' for rate r.
> So for rates other than MCS 7 and OFDM 54 the firmware starts
> transmitting on a fallback rate rather than the rate chosen by AMRR.
> Fix this by always pointing the firmware at the first slot:
>
> Index: if_iwm.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
> retrieving revision 1.71
> diff -u -p -r1.71 if_iwm.c
> --- if_iwm.c 14 Dec 2015 08:34:56 -0000 1.71
> +++ if_iwm.c 5 Jan 2016 13:32:24 -0000
> @@ -3867,13 +3867,7 @@ iwm_tx_fill_cmd(struct iwm_softc *sc, st
> ridx = sc->sc_fixed_ridx;
> } else {
> /* for data frames, use RS table */
> -#ifndef IEEE80211_NO_HT
> - if (ni->ni_flags & IEEE80211_NODE_HT) {
> - tx->initial_rate_index =
> - (nitems(iwm_mcs2ridx) - 1) - ni->ni_txmcs;
> - } else
> -#endif
> - tx->initial_rate_index = (nrates - 1) - ni->ni_txrate;
> + tx->initial_rate_index = 0;
> tx->tx_flags |= htole32(IWM_TX_CMD_FLG_STA_RATE);
> DPRINTFN(12, ("start with txrate %d\n",
> tx->initial_rate_index));
> #ifndef IEEE80211_NO_HT
Make sense to me; ok kettenis@
> iwn still populates this table once after association and doesn't
> update it, so the table is static and always looks like this:
>
> 0 1 n-2 n-1 n
> MCS 7, MCS 6, ..., MCS 0, MCS 0, MCS 0
>
> We select a slot for the firmware to start off from based on AMRR's
> current choice. This is fine for now but will have to change once we
> support more MCS since the table isn't large enough for all of them
> (which is why iwm already uses a dynamic scheme).
>
> The problem I'd like to fix is that in 11n mode iwn's table currently
> contains MCS 7 to 0, but no legacy rates. This will cause transmit
> problems in case the environment is so noisy that MCS/OFDM won't work.
> So make the firmware fall back to the lowest legacy rate if all MCS
> have failed.
> This means we'll fall back to CCK (11b) rates on 2GHz which may be
> the only way to get data through in noisy environments (such as
> the CCC congress, for instance -- hint for benno@ and phessler@).
Hmm, that sounds abit suboptimal. Is your plan tomake the rate table
dynamic as well? Or should AMRR force the card back into 11a/11g mode
if it doesn't succeed in transferringany packets at MCS-0?
No real objection to this as a first step.
> Index: if_iwn.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
> retrieving revision 1.149
> diff -u -p -r1.149 if_iwn.c
> --- if_iwn.c 4 Jan 2016 13:54:19 -0000 1.149
> +++ if_iwn.c 5 Jan 2016 09:46:06 -0000
> @@ -3439,9 +3439,21 @@ iwn_set_link_quality(struct iwn_softc *s
> }
> /* Fill the rest with MCS 0. */
> rinfo = &iwn_rates[iwn_mcs2ridx[0]];
> - while (i < IWN_MAX_TX_RETRIES) {
> + while (i < IWN_MAX_TX_RETRIES - 1) {
> linkq.retry[i].plcp = rinfo->ht_plcp;
> linkq.retry[i].rflags = rinfo->ht_flags;
> + linkq.retry[i].rflags |= IWN_RFLAG_ANT(txant);
> + i++;
> + }
> +
> + /* Fill the last slot 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];
> + while (i < IWN_MAX_TX_RETRIES) {
> + linkq.retry[i].plcp = rinfo->plcp;
> + linkq.retry[i].rflags = rinfo->flags;
> linkq.retry[i].rflags |= IWN_RFLAG_ANT(txant);
> i++;
> }
>
>