Improve the new ieee80211_{min,max}_rates() APIs and fix regressions.
authorstsp <stsp@openbsd.org>
Tue, 30 May 2017 16:21:55 +0000 (16:21 +0000)
committerstsp <stsp@openbsd.org>
Tue, 30 May 2017 16:21:55 +0000 (16:21 +0000)
Instead of returning an index into ni_rates, return the RVAL of the
basic rate we want to use. This allows a driver to unambiguously map
the basic rate to the corresponding hardware-specific rate value, and
reduces the possibility of bugs where indices are used with arrays
they weren't intended for.

Adjust iwn(4) accordingly, and use the lowest instead of the highest
basic rate in iwn_tx() to cope better in noisy environments.

Fixes association problems on 5GHz reported by tb@

sys/dev/pci/if_iwn.c
sys/net80211/ieee80211.c

index 6d7efb1..bc51f0a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_iwn.c,v 1.187 2017/05/30 11:01:38 stsp Exp $       */
+/*     $OpenBSD: if_iwn.c,v 1.188 2017/05/30 16:21:55 stsp Exp $       */
 
 /*-
  * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
@@ -179,6 +179,7 @@ void                iwn5000_update_sched(struct iwn_softc *, int, int, uint8_t,
 void           iwn5000_reset_sched(struct iwn_softc *, int, int);
 int            iwn_tx(struct iwn_softc *, struct mbuf *,
                    struct ieee80211_node *);
+int            iwn_rval2ridx(int);
 void           iwn_start(struct ifnet *);
 void           iwn_watchdog(struct ifnet *);
 int            iwn_ioctl(struct ifnet *, u_long, caddr_t);
@@ -2853,6 +2854,19 @@ iwn5000_reset_sched(struct iwn_softc *sc, int qid, int idx)
        }
 }
 
+int
+iwn_rval2ridx(int rval)
+{
+       int ridx;
+
+       for (ridx = 0; ridx < nitems(iwn_rates); ridx++) {
+               if (rval == iwn_rates[ridx].rate)
+                       break;
+       }
+
+       return ridx;
+}
+
 int
 iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
 {
@@ -2896,7 +2910,7 @@ iwn_tx(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
        /* Choose a TX rate index. */
        if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
            type != IEEE80211_FC0_TYPE_DATA)
-               ridx = wn->ridx[ieee80211_max_basic_rate(ic)];
+               ridx = iwn_rval2ridx(ieee80211_min_basic_rate(ic));
        else if (ic->ic_fixed_mcs != -1)
                ridx = sc->fixed_ridx;
        else if (ic->ic_fixed_rate != -1)
@@ -3467,7 +3481,7 @@ iwn_set_link_quality(struct iwn_softc *sc, struct ieee80211_node *ni)
                }
 
                /* Fill the rest with the lowest basic rate. */
-               rinfo = &iwn_rates[wn->ridx[ieee80211_min_basic_rate(ic)]];
+               rinfo = &iwn_rates[iwn_rval2ridx(ieee80211_min_basic_rate(ic))];
                while (i < IWN_MAX_TX_RETRIES) {
                        linkq.retry[i].plcp = rinfo->plcp;
                        linkq.retry[i].rflags = rinfo->flags;
index a5da6f1..4daabc6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ieee80211.c,v 1.59 2017/05/30 11:00:38 stsp Exp $     */
+/*     $OpenBSD: ieee80211.c,v 1.60 2017/05/30 16:21:55 stsp Exp $     */
 /*     $NetBSD: ieee80211.c,v 1.19 2004/06/06 05:45:29 dyoung Exp $    */
 
 /*-
@@ -716,37 +716,45 @@ int
 ieee80211_min_basic_rate(struct ieee80211com *ic)
 {
        struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
-       int i;
+       int i, min, rval;
+
+       min = -1;
 
        for (i = 0; i < rs->rs_nrates; i++) {
-               if (rs->rs_rates[i] & IEEE80211_RATE_BASIC)
-                       return i;
+               if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0)
+                       continue;
+               rval = (rs->rs_rates[i] & IEEE80211_RATE_VAL);
+               if (min == -1)
+                       min = rval;
+               else if (rval < min)
+                       min = rval;
        }
 
-       return 0;
+       /* Default to 1 Mbit/s on 2GHz and 6 Mbit/s on 5GHz. */
+       if (min == -1)
+               min = IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? 2 : 12;
+
+       return min;
 }
 
 int
 ieee80211_max_basic_rate(struct ieee80211com *ic)
 {
        struct ieee80211_rateset *rs = &ic->ic_bss->ni_rates;
-       int i, best, rval, best_rval;
+       int i, max, 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);
+       /* Default to 1 Mbit/s on 2GHz and 6 Mbit/s on 5GHz. */
+       max = IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan) ? 2 : 12;
 
        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;
-               }
+               if (rval > max)
+                       max = rval;
        }
 
-       return best;
+       return max;
 }
 
 /*