We inherited a bug(?) from Linux where the iwm driver adds all mandatory
OFDM rates (up to 24Mbit/s) to the ACK rate set if the AP does not
advertise _any_ basic OFDM rates. This kills traffic at the edge of
the WLAN cell because e.g. RTS is sent at 24Mbit/s instead of 6Mbit/s
and rarely gets through to the AP.
(I have not been able to convince the firmware to send RTS at lower
rates than 6 Mbit/s while in 11n mode.)

This code was also inconsistent with the comments in this function
which confidently state in two places (emphasis mine):

  ""add all mandatory rates that are LOWER THAN all of the
    basic rates to these bitmaps."""

  """ just add ANY LOWER rates to the ACK rate bitmap."""

So then instead of adding any lower rates, they add all of them if
none was given?!? Let's just add the lowest one if none was given.
Invisible in this diff: The lowest rates are always added by code below.

With this, ssh connections to a laptop at the edge of the WLAN cell
remain somewhat usable during pkg_add -u.

Index: dev/pci/if_iwm.c
==================================================================
--- dev/pci/if_iwm.c
+++ dev/pci/if_iwm.c
@@ -4916,12 +4916,12 @@
 iwm_ack_rates(struct iwm_softc *sc, struct iwm_node *in, int *cck_rates,
     int *ofdm_rates)
 {
        struct ieee80211_node *ni = &in->in_ni;
        struct ieee80211_rateset *rs = &ni->ni_rates;
-       int lowest_present_ofdm = 100;
-       int lowest_present_cck = 100;
+       int lowest_present_ofdm = -1;
+       int lowest_present_cck = -1;
        uint8_t cck = 0;
        uint8_t ofdm = 0;
        int i;
 
        if (ni->ni_chan == IEEE80211_CHAN_ANYC ||
@@ -4928,19 +4928,19 @@
            IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
                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)
+                       if (lowest_present_cck == -1 || lowest_present_cck > i)
                                lowest_present_cck = i;
                }
        }
        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)
+               if (lowest_present_ofdm == -1 || lowest_present_ofdm > i)
                        lowest_present_ofdm = i;
        }
 
        /*
         * Now we've got the basic rates as bitmaps in the ofdm and cck

Reply via email to