Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151154230
D49761.id153502.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D49761.id153502.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D49761: LinuxKPI: 802.11: try to avoid firmware crashes with sta bw > channel width
Attached
Detach File
Event Timeline
Log In to Comment