> 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++;
>               }
> 
> 

Reply via email to