Page MenuHomeFreeBSD

D49761.id153502.diff
No OneTemporary

D49761.id153502.diff

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -365,9 +365,81 @@
return (0);
}
+static enum ieee80211_sta_rx_bw
+lkpi_cw_to_rx_bw(enum nl80211_chan_width cw)
+{
+ switch (cw) {
+ case NL80211_CHAN_WIDTH_320:
+ return (IEEE80211_STA_RX_BW_320);
+ case NL80211_CHAN_WIDTH_160:
+ case NL80211_CHAN_WIDTH_80P80:
+ return (IEEE80211_STA_RX_BW_160);
+ case NL80211_CHAN_WIDTH_80:
+ return (IEEE80211_STA_RX_BW_80);
+ case NL80211_CHAN_WIDTH_40:
+ return (IEEE80211_STA_RX_BW_40);
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ return (IEEE80211_STA_RX_BW_20);
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
+ /* Unsupported input. */
+ return (IEEE80211_STA_RX_BW_20);
+ }
+}
+
+static enum nl80211_chan_width
+lkpi_rx_bw_to_cw(enum ieee80211_sta_rx_bw rx_bw)
+{
+ switch (rx_bw) {
+ case IEEE80211_STA_RX_BW_20:
+ return (NL80211_CHAN_WIDTH_20); /* _NOHT */
+ case IEEE80211_STA_RX_BW_40:
+ return (NL80211_CHAN_WIDTH_40);
+ case IEEE80211_STA_RX_BW_80:
+ return (NL80211_CHAN_WIDTH_80);
+ case IEEE80211_STA_RX_BW_160:
+ return (NL80211_CHAN_WIDTH_160); /* 80P80 */
+ case IEEE80211_STA_RX_BW_320:
+ return (NL80211_CHAN_WIDTH_320);
+ }
+}
+
+static void
+lkpi_sync_chanctx_cw_from_rx_bw(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, struct ieee80211_sta *sta)
+{
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ enum ieee80211_sta_rx_bw old_bw;
+ uint32_t changed;
+
+ chanctx_conf = rcu_dereference_protected(vif->bss_conf.chanctx_conf,
+ lockdep_is_held(&hw->wiphy->mtx));
+ if (chanctx_conf == NULL)
+ return;
+
+ old_bw = lkpi_cw_to_rx_bw(chanctx_conf->def.width);
+ if (old_bw == sta->deflink.bandwidth)
+ return;
+
+ chanctx_conf->def.width = lkpi_rx_bw_to_cw(sta->deflink.bandwidth);
+ if (chanctx_conf->def.width == NL80211_CHAN_WIDTH_20 &&
+ !sta->deflink.ht_cap.ht_supported)
+ chanctx_conf->def.width = NL80211_CHAN_WIDTH_20_NOHT;
+
+ chanctx_conf->min_def = chanctx_conf->def;
+
+ vif->bss_conf.chanreq.oper.width = chanctx_conf->def.width;
+
+ changed = IEEE80211_CHANCTX_CHANGE_MIN_WIDTH;
+ changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
+ lkpi_80211_mo_change_chanctx(hw, chanctx_conf, changed);
+}
+
#if defined(LKPI_80211_HT)
static void
-lkpi_sta_sync_ht_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni)
+lkpi_sta_sync_ht_from_ni(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_node *ni)
{
struct ieee80211vap *vap;
uint8_t *ie;
@@ -399,7 +471,8 @@
sta->deflink.ht_cap.cap = htcap->cap_info;
sta->deflink.ht_cap.mcs = htcap->mcs;
- if ((sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) != 0)
+ if ((sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) != 0 &&
+ IEEE80211_IS_CHAN_HT40(ni->ni_chan))
sta->deflink.bandwidth = IEEE80211_STA_RX_BW_40;
else
sta->deflink.bandwidth = IEEE80211_STA_RX_BW_20;
@@ -435,14 +508,16 @@
#if defined(LKPI_80211_VHT)
static void
-lkpi_sta_sync_vht_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni)
+lkpi_sta_sync_vht_from_ni(struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+ struct ieee80211_node *ni)
{
uint32_t width;
int rx_nss;
uint16_t rx_mcs_map;
uint8_t mcs;
- if ((ni->ni_flags & IEEE80211_NODE_VHT) == 0) {
+ if ((ni->ni_flags & IEEE80211_NODE_VHT) == 0 ||
+ !IEEE80211_IS_CHAN_VHT_5GHZ(ni->ni_chan)) {
sta->deflink.vht_cap.vht_supported = false;
return;
}
@@ -507,15 +582,25 @@
#endif
static void
-lkpi_sta_sync_from_ni(struct ieee80211_sta *sta, struct ieee80211_node *ni)
+lkpi_sta_sync_from_ni(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta, struct ieee80211_node *ni, bool updchnctx)
{
#if defined(LKPI_80211_HT)
- lkpi_sta_sync_ht_from_ni(sta, ni);
+ lkpi_sta_sync_ht_from_ni(vif, sta, ni);
#endif
#if defined(LKPI_80211_VHT)
- lkpi_sta_sync_vht_from_ni(sta, ni);
+ lkpi_sta_sync_vht_from_ni(vif, sta, ni);
#endif
+ /*
+ * We are also called from node allocation which net80211
+ * an do even on ifconfig down; in that case the chanctx
+ * may still be valid and we get a discrepancy between
+ * sta and chanctx. Thus do not update the chanctx if
+ * there is one when called from lkpi_lsta_alloc().
+ */
+ if (updchnctx)
+ lkpi_sync_chanctx_cw_from_rx_bw(hw, vif, sta);
}
static uint8_t
@@ -686,7 +771,9 @@
sta->deflink.bandwidth = IEEE80211_STA_RX_BW_20;
sta->deflink.rx_nss = 1;
- lkpi_sta_sync_from_ni(sta, ni);
+ wiphy_lock(hw->wiphy);
+ lkpi_sta_sync_from_ni(hw, vif, sta, ni, false);
+ wiphy_unlock(hw->wiphy);
IMPROVE("he, eht, bw_320, ... smps_mode, ..");
@@ -1837,6 +1924,7 @@
IMPROVE("Check vht_cap from band not just chan?");
KASSERT(ni->ni_chan != NULL && ni->ni_chan != IEEE80211_CHAN_ANYC,
("%s:%d: ni %p ni_chan %p\n", __func__, __LINE__, ni, ni->ni_chan));
+
#ifdef LKPI_80211_HT
if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) {
if (IEEE80211_IS_CHAN_HT40(ni->ni_chan))
@@ -1846,7 +1934,7 @@
}
#endif
#ifdef LKPI_80211_VHT
- if (IEEE80211_IS_CHAN_VHT(ni->ni_chan)) {
+ if (IEEE80211_IS_CHAN_VHT_5GHZ(ni->ni_chan)) {
#ifdef __notyet__
if (IEEE80211_IS_CHAN_VHT80P80(ni->ni_chan))
chanctx_conf->def.width = NL80211_CHAN_WIDTH_80P80;
@@ -2656,7 +2744,6 @@
}
bss_changed |= lkpi_update_dtim_tsf(vif, ni, vap, __func__, __LINE__);
-
lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed);
/* - change_chanctx (if needed)
@@ -2691,7 +2778,7 @@
sta->deflink.rx_nss = MAX(1, sta->deflink.rx_nss);
IMPROVE("Is this the right spot, has net80211 done all updates already?");
- lkpi_sta_sync_from_ni(sta, ni);
+ lkpi_sta_sync_from_ni(hw, vif, sta, ni, true);
/* Update sta_state (ASSOC to AUTHORIZED). */
KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni));
@@ -3877,7 +3964,8 @@
}
#endif
#if defined(LKPI_80211_VHT)
- if ((vap->iv_vht_flags & IEEE80211_FVHT_VHT) != 0) {
+ if (band == NL80211_BAND_5GHZ &&
+ (vap->iv_vht_flags & IEEE80211_FVHT_VHT) != 0) {
struct ieee80211_channel *c;
c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan,
@@ -5379,7 +5467,7 @@
NL80211_BAND_5GHZ);
#ifdef LKPI_80211_VHT
- if (hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.vht_supported){
+ if (hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.vht_supported) {
ic->ic_flags_ext |= IEEE80211_FEXT_VHT;
ic->ic_vht_cap.vht_cap_info =
diff --git a/sys/compat/linuxkpi/common/src/linux_80211_macops.c b/sys/compat/linuxkpi/common/src/linux_80211_macops.c
--- a/sys/compat/linuxkpi/common/src/linux_80211_macops.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211_macops.c
@@ -551,6 +551,9 @@
lhw->ops->bss_info_changed == NULL)
return;
+ if (changed == 0)
+ return;
+
LKPI_80211_TRACE_MO("hw %p vif %p conf %p changed %#jx", hw, vif, conf, (uintmax_t)changed);
if (lhw->ops->link_info_changed != NULL)
lhw->ops->link_info_changed(hw, vif, conf, changed);

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 7, 11:28 AM (18 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31028042
Default Alt Text
D49761.id153502.diff (6 KB)

Event Timeline