From 0b25d076ee0abe5921de9e3baa3ef606c50fd0d9 Mon Sep 17 00:00:00 2001 From: stsp Date: Tue, 30 May 2017 16:21:55 +0000 Subject: [PATCH] Improve the new ieee80211_{min,max}_rates() APIs and fix regressions. 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 | 20 +++++++++++++++++--- sys/net80211/ieee80211.c | 36 ++++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index 6d7efb15f0b..bc51f0a6db5 100644 --- a/sys/dev/pci/if_iwn.c +++ b/sys/dev/pci/if_iwn.c @@ -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 @@ -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; diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index a5da6f1050b..4daabc68d40 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -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; } /* -- 2.20.1