All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] mac80211 MLO updates
@ 2022-06-01  7:39 Johannes Berg
  2022-06-01  7:39 ` [PATCH 01/15] mac80211: split bss_info_changed method Johannes Berg
                   ` (14 more replies)
  0 siblings, 15 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless

Hi,

Here's the next (large) set of mac80211 MLO updates, though it's of
course still _far_ from complete :-)

Next on my list:
 - auth/assoc
 - datapath

johannes



^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 01/15] mac80211: split bss_info_changed method
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01 19:31   ` Jeff Johnson
  2022-10-18  8:47     ` Wen Gong
  2022-06-01  7:39 ` [PATCH 02/15] mac80211: add per-link configuration pointer Johannes Berg
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Split the bss_info_changed method to vif_cfg_changed and
link_info_changed, with the latter getting a link ID.
Also change the 'changed' parameter to u64 already, we
know we need that.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/admtek/adm8211.c         |   2 +-
 drivers/net/wireless/ath/ar5523/ar5523.c      |   2 +-
 drivers/net/wireless/ath/ath10k/mac.c         |   2 +-
 drivers/net/wireless/ath/ath11k/mac.c         |   2 +-
 drivers/net/wireless/ath/ath5k/mac80211-ops.c |   2 +-
 drivers/net/wireless/ath/ath9k/htc_drv_main.c |   2 +-
 drivers/net/wireless/ath/ath9k/main.c         |   2 +-
 drivers/net/wireless/ath/carl9170/main.c      |   2 +-
 drivers/net/wireless/ath/wcn36xx/main.c       |   6 +-
 drivers/net/wireless/atmel/at76c50x-usb.c     |   2 +-
 drivers/net/wireless/broadcom/b43/main.c      |   4 +-
 .../net/wireless/broadcom/b43legacy/main.c    |   2 +-
 .../broadcom/brcm80211/brcmsmac/mac80211_if.c |   2 +-
 drivers/net/wireless/intel/iwlegacy/common.c  |   7 +-
 drivers/net/wireless/intel/iwlegacy/common.h  |   2 +-
 drivers/net/wireless/intel/iwlwifi/dvm/agn.h  |   2 +-
 drivers/net/wireless/intel/iwlwifi/dvm/rxon.c |   2 +-
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |   6 +-
 drivers/net/wireless/intersil/p54/main.c      |   2 +-
 drivers/net/wireless/mac80211_hwsim.c         |   6 +-
 .../net/wireless/marvell/libertas_tf/main.c   |   2 +-
 drivers/net/wireless/marvell/mwl8k.c          |   2 +-
 .../net/wireless/mediatek/mt76/mt7603/main.c  |   2 +-
 .../net/wireless/mediatek/mt76/mt7615/main.c  |   2 +-
 drivers/net/wireless/mediatek/mt76/mt76x02.h  |   2 +-
 .../net/wireless/mediatek/mt76/mt76x02_util.c |   2 +-
 .../net/wireless/mediatek/mt76/mt7915/main.c  |   2 +-
 .../net/wireless/mediatek/mt76/mt7921/main.c  |   2 +-
 drivers/net/wireless/mediatek/mt7601u/main.c  |   2 +-
 drivers/net/wireless/purelifi/plfxlc/mac.c    |   5 +-
 drivers/net/wireless/ralink/rt2x00/rt2x00.h   |   2 +-
 .../net/wireless/ralink/rt2x00/rt2x00mac.c    |   2 +-
 .../wireless/realtek/rtl818x/rtl8180/dev.c    |   2 +-
 .../wireless/realtek/rtl818x/rtl8187/dev.c    |   2 +-
 .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c |   2 +-
 drivers/net/wireless/realtek/rtlwifi/core.c   |   2 +-
 drivers/net/wireless/realtek/rtw88/mac80211.c |   2 +-
 drivers/net/wireless/realtek/rtw89/mac80211.c |   2 +-
 drivers/net/wireless/rsi/rsi_91x_mac80211.c   |   2 +-
 drivers/net/wireless/silabs/wfx/sta.c         |   2 +-
 drivers/net/wireless/silabs/wfx/sta.h         |   2 +-
 drivers/net/wireless/st/cw1200/sta.c          |   4 +-
 drivers/net/wireless/st/cw1200/sta.h          |   2 +-
 drivers/net/wireless/ti/wl1251/main.c         |   2 +-
 drivers/net/wireless/ti/wlcore/main.c         |   2 +-
 drivers/net/wireless/zydas/zd1211rw/zd_mac.c  |   4 +-
 drivers/staging/vt6655/device_main.c          |   2 +-
 drivers/staging/vt6656/main_usb.c             |   2 +-
 include/net/mac80211.h                        |  28 +++-
 net/mac80211/cfg.c                            |  31 ++--
 net/mac80211/chan.c                           |   9 +-
 net/mac80211/driver-ops.h                     |  35 ++++-
 net/mac80211/ibss.c                           |   2 +-
 net/mac80211/ieee80211_i.h                    |   6 +-
 net/mac80211/iface.c                          |   5 +-
 net/mac80211/main.c                           |  80 +++++++++-
 net/mac80211/mesh.c                           |   6 +-
 net/mac80211/mlme.c                           |  16 +-
 net/mac80211/offchannel.c                     |   8 +-
 net/mac80211/sta_info.c                       |   2 +-
 net/mac80211/tdls.c                           |   2 +-
 net/mac80211/trace.h                          | 138 +++++++++++-------
 net/mac80211/util.c                           |   4 +-
 net/mac80211/vht.c                            |   2 +-
 64 files changed, 324 insertions(+), 172 deletions(-)

diff --git a/drivers/net/wireless/admtek/adm8211.c b/drivers/net/wireless/admtek/adm8211.c
index 2db9c948c0fc..6bee16b207d1 100644
--- a/drivers/net/wireless/admtek/adm8211.c
+++ b/drivers/net/wireless/admtek/adm8211.c
@@ -1311,7 +1311,7 @@ static int adm8211_config(struct ieee80211_hw *dev, u32 changed)
 static void adm8211_bss_info_changed(struct ieee80211_hw *dev,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *conf,
-				     u32 changes)
+				     u64 changes)
 {
 	struct adm8211_priv *priv = dev->priv;
 
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
index 4cd06a0942d4..6f937d2cc126 100644
--- a/drivers/net/wireless/ath/ar5523/ar5523.c
+++ b/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -1273,7 +1273,7 @@ static int ar5523_write_associd(struct ar5523 *ar, struct ieee80211_vif *vif)
 static void ar5523_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *bss,
-				    u32 changed)
+				    u64 changed)
 {
 	struct ar5523 *ar = hw->priv;
 	int error;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 409777a15dcb..bc0135868792 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6034,7 +6034,7 @@ static void ath10k_recalculate_mgmt_rate(struct ath10k *ar,
 static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *info,
-				    u32 changed)
+				    u64 changed)
 {
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif = (void *)vif->drv_priv;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 7ec0df2fc107..be102357317b 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -3091,7 +3091,7 @@ static int ath11k_mac_config_obss_pd(struct ath11k *ar,
 static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
 					   struct ieee80211_vif *vif,
 					   struct ieee80211_bss_conf *info,
-					   u32 changed)
+					   u64 changed)
 {
 	struct ath11k *ar = hw->priv;
 	struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif);
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 0df0fa1da181..8da232e81518 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -250,7 +250,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
 
 static void
 ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		       struct ieee80211_bss_conf *bss_conf, u32 changes)
+		       struct ieee80211_bss_conf *bss_conf, u64 changes)
 {
 	struct ath5k_vif *avf = (void *)vif->drv_priv;
 	struct ath5k_hw *ah = hw->priv;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 3a5ec4da6a38..14d713e03872 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1509,7 +1509,7 @@ static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv)
 static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
 				       struct ieee80211_bss_conf *bss_conf,
-				       u32 changed)
+				       u64 changed)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath_hw *ah = priv->ah;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 56c2681e5192..729f8ee9644d 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1863,7 +1863,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
 static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif,
 				   struct ieee80211_bss_conf *bss_conf,
-				   u32 changed)
+				   u64 changed)
 {
 #define CHECK_ANI				\
 	(BSS_CHANGED_ASSOC |			\
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index e28a5f3085c0..3d881028bd00 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1032,7 +1032,7 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
 static void carl9170_op_bss_info_changed(struct ieee80211_hw *hw,
 					 struct ieee80211_vif *vif,
 					 struct ieee80211_bss_conf *bss_conf,
-					 u32 changed)
+					 u64 changed)
 {
 	struct ar9170 *ar = hw->priv;
 	struct ath_common *common = &ar->common;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 72ba2e2fc93a..5f5006ac4ba8 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -872,7 +872,7 @@ void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates)
 static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *bss_conf,
-				     u32 changed)
+				     u64 changed)
 {
 	struct wcn36xx *wcn = hw->priv;
 	struct sk_buff *skb = NULL;
@@ -880,8 +880,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
 	enum wcn36xx_hal_link_state link_state;
 	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
 
-	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
-		    vif, changed);
+	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%llx\n",
+		    vif, (unsigned long long)changed);
 
 	mutex_lock(&wcn->conf_mutex);
 
diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c
index 7582761c61e2..24e609c1f523 100644
--- a/drivers/net/wireless/atmel/at76c50x-usb.c
+++ b/drivers/net/wireless/atmel/at76c50x-usb.c
@@ -2033,7 +2033,7 @@ static int at76_config(struct ieee80211_hw *hw, u32 changed)
 static void at76_bss_info_changed(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
 				  struct ieee80211_bss_conf *conf,
-				  u32 changed)
+				  u64 changed)
 {
 	struct at76_priv *priv = hw->priv;
 
diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 17bcec5f3ff7..e3121a9d0579 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -366,7 +366,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev);
 static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *conf,
-				    u32 changed);
+				    u64 changed);
 
 static int b43_ratelimit(struct b43_wl *wl)
 {
@@ -4097,7 +4097,7 @@ static void b43_update_basic_rates(struct b43_wldev *dev, u32 brates)
 static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *conf,
-				    u32 changed)
+				    u64 changed)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
 	struct b43_wldev *dev;
diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c
index eec3af9c3745..96d5a034c09b 100644
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
@@ -2806,7 +2806,7 @@ static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u32 brates
 static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *conf,
-				    u32 changed)
+				    u64 changed)
 {
 	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
 	struct b43legacy_wldev *dev;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
index e6cd638a85d6..fd3c131c622c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
@@ -582,7 +582,7 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
 static void
 brcms_ops_bss_info_changed(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif,
-			struct ieee80211_bss_conf *info, u32 changed)
+			struct ieee80211_bss_conf *info, u64 changed)
 {
 	struct brcms_info *wl = hw->priv;
 	struct bcma_device *core = wl->wlc->hw->d11core;
diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c
index b01945415be6..6975f0297f03 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.c
+++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -5311,13 +5311,13 @@ il_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
 void
 il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			struct ieee80211_bss_conf *bss_conf, u32 changes)
+			struct ieee80211_bss_conf *bss_conf, u64 changes)
 {
 	struct il_priv *il = hw->priv;
 	int ret;
 
 	mutex_lock(&il->mutex);
-	D_MAC80211("enter: changes 0x%x\n", changes);
+	D_MAC80211("enter: changes 0x%llx\n", (unsigned long long)changes);
 
 	if (!il_is_alive(il)) {
 		D_MAC80211("leave - not alive\n");
@@ -5438,7 +5438,8 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	}
 
 	if (changes && il_is_associated(il) && vif->cfg.aid) {
-		D_MAC80211("Changes (%#x) while associated\n", changes);
+		D_MAC80211("Changes (%#llx) while associated\n",
+			   (unsigned long long)changes);
 		ret = il_send_rxon_assoc(il);
 		if (!ret) {
 			/* Sync active_rxon with latest change. */
diff --git a/drivers/net/wireless/intel/iwlegacy/common.h b/drivers/net/wireless/intel/iwlegacy/common.h
index 40877ef1fbf2..d1383b4f0f05 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.h
+++ b/drivers/net/wireless/intel/iwlegacy/common.h
@@ -1947,7 +1947,7 @@ il_get_hw_mode(struct il_priv *il, enum nl80211_band band)
 int il_mac_config(struct ieee80211_hw *hw, u32 changed);
 void il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 void il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			     struct ieee80211_bss_conf *bss_conf, u32 changes);
+			     struct ieee80211_bss_conf *bss_conf, u64 changes);
 void il_tx_cmd_protection(struct il_priv *il, struct ieee80211_tx_info *info,
 			  __le16 fc, __le32 *tx_flags);
 
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
index abb8696ba294..411a6f6638b4 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/agn.h
@@ -92,7 +92,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed);
 void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_bss_conf *bss_conf,
-			     u32 changes);
+			     u64 changes);
 void iwlagn_config_ht40(struct ieee80211_conf *conf,
 			struct iwl_rxon_context *ctx);
 void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
index 17a14970edec..45e382fe45a2 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
@@ -1383,7 +1383,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
 void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_bss_conf *bss_conf,
-			     u32 changes)
+			     u64 changes)
 {
 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
 	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index b5257b4fd000..586208506275 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -2181,7 +2181,7 @@ static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm,
 static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
 					     struct ieee80211_vif *vif,
 					     struct ieee80211_bss_conf *bss_conf,
-					     u32 changes)
+					     u64 changes)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	int ret;
@@ -2590,7 +2590,7 @@ static void
 iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *bss_conf,
-				 u32 changes)
+				 u64 changes)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 
@@ -2621,7 +2621,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
 static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *bss_conf,
-				     u32 changes)
+				     u64 changes)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 
diff --git a/drivers/net/wireless/intersil/p54/main.c b/drivers/net/wireless/intersil/p54/main.c
index a9dfe6a3da0d..cc6769a4fec7 100644
--- a/drivers/net/wireless/intersil/p54/main.c
+++ b/drivers/net/wireless/intersil/p54/main.c
@@ -449,7 +449,7 @@ static int p54_get_stats(struct ieee80211_hw *dev,
 static void p54_bss_info_changed(struct ieee80211_hw *dev,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *info,
-				 u32 changed)
+				 u64 changed)
 {
 	struct p54_common *priv = dev->priv;
 
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index b034d34745ab..1bd96b504956 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2101,15 +2101,15 @@ static void mac80211_hwsim_bcn_en_iter(void *data, u8 *mac,
 static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
 					    struct ieee80211_vif *vif,
 					    struct ieee80211_bss_conf *info,
-					    u32 changed)
+					    u64 changed)
 {
 	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
 	struct mac80211_hwsim_data *data = hw->priv;
 
 	hwsim_check_magic(vif);
 
-	wiphy_dbg(hw->wiphy, "%s(changed=0x%x vif->addr=%pM)\n",
-		  __func__, changed, vif->addr);
+	wiphy_dbg(hw->wiphy, "%s(changed=0x%llx vif->addr=%pM)\n",
+		  __func__, (unsigned long long)changed, vif->addr);
 
 	if (changed & BSS_CHANGED_BSSID) {
 		wiphy_dbg(hw->wiphy, "%s: BSSID changed: %pM\n",
diff --git a/drivers/net/wireless/marvell/libertas_tf/main.c b/drivers/net/wireless/marvell/libertas_tf/main.c
index 02a1e1f547d8..21c3e0bdc444 100644
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -417,7 +417,7 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
 static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif,
 			struct ieee80211_bss_conf *bss_conf,
-			u32 changes)
+			u64 changes)
 {
 	struct lbtf_private *priv = hw->priv;
 	struct sk_buff *beacon;
diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c
index 5f1bcfb5e3f6..7eef3a74d124 100644
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
@@ -5163,7 +5163,7 @@ mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
 static void
 mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		       struct ieee80211_bss_conf *info, u32 changed)
+		       struct ieee80211_bss_conf *info, u64 changed)
 {
 	if (vif->type == NL80211_IFTYPE_STATION)
 		mwl8k_bss_info_changed_sta(hw, vif, info, changed);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
index 1f14ecda1f55..088c0a4cf774 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -297,7 +297,7 @@ mt7603_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 
 static void
 mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			struct ieee80211_bss_conf *info, u32 changed)
+			struct ieee80211_bss_conf *info, u64 changed)
 {
 	struct mt7603_dev *dev = hw->priv;
 	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index d992fdea0f32..277c22a4d049 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -576,7 +576,7 @@ static void mt7615_configure_filter(struct ieee80211_hw *hw,
 static void mt7615_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *info,
-				    u32 changed)
+				    u64 changed)
 {
 	struct mt7615_dev *dev = mt7615_hw_dev(hw);
 	struct mt7615_phy *phy = mt7615_hw_phy(hw);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h
index f76fd22ee035..74ad418f5a70 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -187,7 +187,7 @@ void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
 void mt76x02_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps);
 void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
-			      struct ieee80211_bss_conf *info, u32 changed);
+			      struct ieee80211_bss_conf *info, u64 changed);
 void mt76x02_reconfig_complete(struct ieee80211_hw *hw,
 			       enum ieee80211_reconfig_type reconfig_type);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 5bd0a0bae688..a0e2d042751b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -636,7 +636,7 @@ EXPORT_SYMBOL_GPL(mt76x02_sta_ps);
 void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
 			      struct ieee80211_bss_conf *info,
-			      u32 changed)
+			      u64 changed)
 {
 	struct mt76x02_vif *mvif = (struct mt76x02_vif *)vif->drv_priv;
 	struct mt76x02_dev *dev = hw->priv;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 05327b0b6fc3..fbeac9aa2af6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -573,7 +573,7 @@ mt7915_update_bss_color(struct ieee80211_hw *hw,
 static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *info,
-				    u32 changed)
+				    u64 changed)
 {
 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 8532033794bd..63583605d1cd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -637,7 +637,7 @@ static void mt7921_configure_filter(struct ieee80211_hw *hw,
 static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *info,
-				    u32 changed)
+				    u64 changed)
 {
 	struct mt7921_phy *phy = mt7921_hw_phy(hw);
 	struct mt7921_dev *dev = mt7921_hw_dev(hw);
diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c
index 671d8897ae76..6c9c7a61c5c9 100644
--- a/drivers/net/wireless/mediatek/mt7601u/main.c
+++ b/drivers/net/wireless/mediatek/mt7601u/main.c
@@ -132,7 +132,7 @@ mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 
 static void
 mt7601u_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			 struct ieee80211_bss_conf *info, u32 changed)
+			 struct ieee80211_bss_conf *info, u64 changed)
 {
 	struct mt7601u_dev *dev = hw->priv;
 
diff --git a/drivers/net/wireless/purelifi/plfxlc/mac.c b/drivers/net/wireless/purelifi/plfxlc/mac.c
index 90e552532701..b546a963b0a3 100644
--- a/drivers/net/wireless/purelifi/plfxlc/mac.c
+++ b/drivers/net/wireless/purelifi/plfxlc/mac.c
@@ -587,12 +587,13 @@ static void plfxlc_op_configure_filter(struct ieee80211_hw *hw,
 static void plfxlc_op_bss_info_changed(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
 				       struct ieee80211_bss_conf *bss_conf,
-				       u32 changes)
+				       u64 changes)
 {
 	struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
 	int associated;
 
-	dev_dbg(plfxlc_mac_dev(mac), "changes: %x\n", changes);
+	dev_dbg(plfxlc_mac_dev(mac), "changes: %llx\n",
+		(unsigned long long)changes);
 
 	if (mac->type != NL80211_IFTYPE_ADHOC) { /* for STATION */
 		associated = is_valid_ether_addr(bss_conf->bssid);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index 9f6fc40649be..918e0477bb7d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -1479,7 +1479,7 @@ int rt2x00mac_get_stats(struct ieee80211_hw *hw,
 void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 				struct ieee80211_vif *vif,
 				struct ieee80211_bss_conf *bss_conf,
-				u32 changes);
+				u64 changes);
 int rt2x00mac_conf_tx(struct ieee80211_hw *hw,
 		      struct ieee80211_vif *vif, u16 queue,
 		      const struct ieee80211_tx_queue_params *params);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
index 660554a01894..6205d22765c7 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
@@ -574,7 +574,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_get_stats);
 void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 				struct ieee80211_vif *vif,
 				struct ieee80211_bss_conf *bss_conf,
-				u32 changes)
+				u64 changes)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct rt2x00_intf *intf = vif_to_intf(vif);
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
index 025619cd14e8..10e8fdc31879 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
@@ -1500,7 +1500,7 @@ static void rtl8180_conf_erp(struct ieee80211_hw *dev,
 static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *info,
-				     u32 changed)
+				     u64 changed)
 {
 	struct rtl8180_priv *priv = dev->priv;
 	struct rtl8180_vif *vif_priv;
diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
index eb68b2d3caa1..8ab65c888baf 100644
--- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c
@@ -1251,7 +1251,7 @@ static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot,
 static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *info,
-				     u32 changed)
+				     u64 changed)
 {
 	struct rtl8187_priv *priv = dev->priv;
 	struct rtl8187_vif *vif_priv;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
index 0239e12ec8a5..65c4cb1e030c 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -4558,7 +4558,7 @@ rtl8xxxu_wireless_mode(struct ieee80211_hw *hw, struct ieee80211_sta *sta)
 
 static void
 rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			  struct ieee80211_bss_conf *bss_conf, u32 changed)
+			  struct ieee80211_bss_conf *bss_conf, u64 changed)
 {
 	struct rtl8xxxu_priv *priv = hw->priv;
 	struct device *dev = &priv->udev->dev;
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index 5177eb02740e..2f7fd8888d3a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1040,7 +1040,7 @@ EXPORT_SYMBOL_GPL(rtl_update_beacon_work_callback);
 static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    struct ieee80211_bss_conf *bss_conf,
-				    u32 changed)
+				    u64 changed)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 52e2c93d02f0..3ef839035bcf 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -355,7 +355,7 @@ static void rtw_conf_tx(struct rtw_dev *rtwdev,
 static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *conf,
-				     u32 changed)
+				     u64 changed)
 {
 	struct rtw_dev *rtwdev = hw->priv;
 	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 6fc125deba28..4cbd2615c636 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -336,7 +336,7 @@ static void rtw89_station_mode_sta_assoc(struct rtw89_dev *rtwdev,
 static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
 				       struct ieee80211_bss_conf *conf,
-				       u32 changed)
+				       u64 changed)
 {
 	struct rtw89_dev *rtwdev = hw->priv;
 	struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index d4b3834388ab..1dff3d263382 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -783,7 +783,7 @@ static void rsi_switch_channel(struct rsi_hw *adapter,
 static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
 					  struct ieee80211_vif *vif,
 					  struct ieee80211_bss_conf *bss_conf,
-					  u32 changed)
+					  u64 changed)
 {
 	struct rsi_hw *adapter = hw->priv;
 	struct rsi_common *common = adapter->priv;
diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c
index 3fc55c0c0b4d..6fb4ba1282c9 100644
--- a/drivers/net/wireless/silabs/wfx/sta.c
+++ b/drivers/net/wireless/silabs/wfx/sta.c
@@ -506,7 +506,7 @@ static void wfx_enable_beacon(struct wfx_vif *wvif, bool enable)
 }
 
 void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			  struct ieee80211_bss_conf *info, u32 changed)
+			  struct ieee80211_bss_conf *info, u64 changed)
 {
 	struct wfx_dev *wdev = hw->priv;
 	struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
diff --git a/drivers/net/wireless/silabs/wfx/sta.h b/drivers/net/wireless/silabs/wfx/sta.h
index c69b2227e9ac..d9c6bd632b20 100644
--- a/drivers/net/wireless/silabs/wfx/sta.h
+++ b/drivers/net/wireless/silabs/wfx/sta.h
@@ -36,7 +36,7 @@ void wfx_leave_ibss(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 int wfx_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		u16 queue, const struct ieee80211_tx_queue_params *params);
 void wfx_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			  struct ieee80211_bss_conf *info, u32 changed);
+			  struct ieee80211_bss_conf *info, u64 changed);
 int wfx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta);
 int wfx_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta);
 void wfx_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c
index 3f48def51ebc..8eaeb39217ee 100644
--- a/drivers/net/wireless/st/cw1200/sta.c
+++ b/drivers/net/wireless/st/cw1200/sta.c
@@ -1796,14 +1796,14 @@ static int cw1200_set_btcoexinfo(struct cw1200_common *priv)
 void cw1200_bss_info_changed(struct ieee80211_hw *dev,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_bss_conf *info,
-			     u32 changed)
+			     u64 changed)
 {
 	struct cw1200_common *priv = dev->priv;
 	bool do_join = false;
 
 	mutex_lock(&priv->conf_mutex);
 
-	pr_debug("BSS CHANGED:  %08x\n", changed);
+	pr_debug("BSS CHANGED:  %llx\n", (unsigned long long)changed);
 
 	/* TODO: BSS_CHANGED_QOS */
 	/* TODO: BSS_CHANGED_TXPOWER */
diff --git a/drivers/net/wireless/st/cw1200/sta.h b/drivers/net/wireless/st/cw1200/sta.h
index 706dab8e73bf..05e3ab7ccef1 100644
--- a/drivers/net/wireless/st/cw1200/sta.h
+++ b/drivers/net/wireless/st/cw1200/sta.h
@@ -103,7 +103,7 @@ void cw1200_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
 void cw1200_bss_info_changed(struct ieee80211_hw *dev,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_bss_conf *info,
-			     u32 changed);
+			     u64 changed);
 int cw1200_ampdu_action(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif,
 			struct ieee80211_ampdu_params *params);
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index bdc93c4f54ba..340ab4985fe2 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1077,7 +1077,7 @@ static int wl1251_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
 				       struct ieee80211_bss_conf *bss_conf,
-				       u32 changed)
+				       u64 changed)
 {
 	struct wl1251 *wl = hw->priv;
 	struct sk_buff *beacon, *skb;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index ad9560bd9512..d365bdce2a10 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4580,7 +4580,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
 				       struct ieee80211_bss_conf *bss_conf,
-				       u32 changed)
+				       u64 changed)
 {
 	struct wl1271 *wl = hw->priv;
 	struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
index 3ef8533205f9..cd2a4cbcc9d6 100644
--- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
@@ -1278,12 +1278,12 @@ static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble)
 static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif,
 				   struct ieee80211_bss_conf *bss_conf,
-				   u32 changes)
+				   u64 changes)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	int associated;
 
-	dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);
+	dev_dbg_f(zd_mac_dev(mac), "changes: %llx\n", (unsigned long long)changes);
 
 	if (mac->type == NL80211_IFTYPE_MESH_POINT ||
 	    mac->type == NL80211_IFTYPE_ADHOC ||
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 741e1b9d6677..f995c592fd09 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -1396,7 +1396,7 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed)
 
 static void vnt_bss_info_changed(struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
-				 struct ieee80211_bss_conf *conf, u32 changed)
+				 struct ieee80211_bss_conf *conf, u64 changed)
 {
 	struct vnt_private *priv = hw->priv;
 
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 3ab8a7bb9715..897ee0f7fc6b 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -745,7 +745,7 @@ static int vnt_config(struct ieee80211_hw *hw, u32 changed)
 
 static void vnt_bss_info_changed(struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
-				 struct ieee80211_bss_conf *conf, u32 changed)
+				 struct ieee80211_bss_conf *conf, u64 changed)
 {
 	struct vnt_private *priv = hw->priv;
 
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 1520922d21a5..831f14b7ca69 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -273,8 +273,8 @@ struct ieee80211_vif_chanctx_switch {
 /**
  * enum ieee80211_bss_change - BSS change notification flags
  *
- * These flags are used with the bss_info_changed() callback
- * to indicate which BSS parameter changed.
+ * These flags are used with the bss_info_changed(), link_info_changed()
+ * and vif_cfg_changed() callbacks to indicate which parameter(s) changed.
  *
  * @BSS_CHANGED_ASSOC: association status changed (associated/disassociated),
  *	also implies a change in the AID.
@@ -3524,6 +3524,22 @@ struct ieee80211_prep_tx_info {
  *	for association indication. The @changed parameter indicates which
  *	of the bss parameters has changed when a call is made. The callback
  *	can sleep.
+ *	Note: this callback is called if @vif_cfg_changed or @link_info_changed
+ *	are not implemented.
+ *
+ * @vif_cfg_changed: Handler for configuration requests related to interface
+ *	(MLD) parameters from &struct ieee80211_vif_cfg that vary during the
+ *	lifetime of the interface (e.g. assoc status, IP addresses, etc.)
+ *	The @changed parameter indicates which value changed.
+ *	The callback can sleep.
+ *
+ * @link_info_changed: Handler for configuration requests related to link
+ *	parameters from &struct ieee80211_bss_conf that are related to an
+ *	individual link. e.g. legacy/HT/VHT/... rate information.
+ *	The @changed parameter indicates which value changed, and the @link_id
+ *	parameter indicates the link ID. Note that the @link_id will be 0 for
+ *	non-MLO connections.
+ *	The callback can sleep.
  *
  * @prepare_multicast: Prepare for multicast filter configuration.
  *	This callback is optional, and its return value is passed
@@ -4032,7 +4048,13 @@ struct ieee80211_ops {
 	void (*bss_info_changed)(struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *info,
-				 u32 changed);
+				 u64 changed);
+	void (*vif_cfg_changed)(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				u64 changed);
+	void (*link_info_changed)(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif,
+				  u64 link_id, u32 changed);
 
 	int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
 	void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 040a766b8c19..ffd26db89f33 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -39,7 +39,8 @@ static void ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata,
 		memcpy(sdata->vif.bss_conf.mu_group.position,
 		       params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN,
 		       WLAN_USER_POSITION_LEN);
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MU_GROUPS);
+		ieee80211_link_info_change_notify(sdata, 0,
+						  BSS_CHANGED_MU_GROUPS);
 		/* don't care about endianness - just check for 0 */
 		memcpy(&membership, params->vht_mumimo_groups,
 		       WLAN_MEMBERSHIP_LEN);
@@ -1337,7 +1338,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
 		err |= BSS_CHANGED_HE_BSS_COLOR;
 	}
 
-	ieee80211_bss_info_change_notify(sdata, err);
+	ieee80211_link_info_change_notify(sdata, 0, err);
 	return 0;
 }
 
@@ -1418,7 +1419,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
 	sdata->beacon_rate_set = false;
 	sdata->vif.cfg.ssid_len = 0;
 	clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
+	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_BEACON_ENABLED);
 
 	if (sdata->wdev.cac_started) {
 		chandef = sdata->vif.bss_conf.chandef;
@@ -2351,7 +2352,7 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
 	if (_chg_mesh_attr(NL80211_MESHCONF_HT_OPMODE, mask)) {
 		conf->ht_opmode = nconf->ht_opmode;
 		sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode;
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
+		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_HT);
 	}
 	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, mask))
 		conf->dot11MeshHWMPactivePathToRootTimeout =
@@ -2506,7 +2507,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
 		changed |= BSS_CHANGED_P2P_PS;
 	}
 
-	ieee80211_bss_info_change_notify(sdata, changed);
+	ieee80211_link_info_change_notify(sdata, 0, changed);
 
 	return 0;
 }
@@ -2547,7 +2548,7 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
 		return -EINVAL;
 	}
 
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
+	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_QOS);
 
 	return 0;
 }
@@ -2696,7 +2697,7 @@ static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
 	memcpy(sdata->vif.bss_conf.mcast_rate, rate,
 	       sizeof(int) * NUM_NL80211_BANDS);
 
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MCAST_RATE);
+	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_MCAST_RATE);
 
 	return 0;
 }
@@ -3030,7 +3031,7 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
 	/* tell the driver upon association, unless already associated */
 	if (sdata->u.mgd.associated &&
 	    sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
+		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_CQM);
 
 	return 0;
 }
@@ -3055,7 +3056,7 @@ static int ieee80211_set_cqm_rssi_range_config(struct wiphy *wiphy,
 	/* tell the driver upon association, unless already associated */
 	if (sdata->u.mgd.associated &&
 	    sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
+		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_CQM);
 
 	return 0;
 }
@@ -3393,7 +3394,7 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
 	if (err)
 		return err;
 
-	ieee80211_bss_info_change_notify(sdata, changed);
+	ieee80211_link_info_change_notify(sdata, 0, changed);
 
 	if (sdata->deflink.csa_block_tx) {
 		ieee80211_wake_vif_queues(local, sdata,
@@ -3681,7 +3682,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 					  params->count, params->block_tx);
 
 	if (changed) {
-		ieee80211_bss_info_change_notify(sdata, changed);
+		ieee80211_link_info_change_notify(sdata, 0, changed);
 		drv_channel_switch_beacon(sdata, &params->chandef);
 	} else {
 		/* if the beacon didn't change, we can finalize immediately */
@@ -3984,7 +3985,7 @@ static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
 
 	ret = ieee80211_vif_change_bandwidth(sdata, chandef, &changed);
 	if (ret == 0)
-		ieee80211_bss_info_change_notify(sdata, changed);
+		ieee80211_link_info_change_notify(sdata, 0, changed);
 
 	return ret;
 }
@@ -4393,7 +4394,7 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
 	sdata->vif.bss_conf.he_bss_color.enabled = enable;
 	changed |= BSS_CHANGED_HE_BSS_COLOR;
 
-	ieee80211_bss_info_change_notify(sdata, changed);
+	ieee80211_link_info_change_notify(sdata, 0, changed);
 
 	if (!sdata->vif.bss_conf.nontransmitted && sdata->vif.mbssid_tx_vif) {
 		struct ieee80211_sub_if_data *child;
@@ -4403,8 +4404,8 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
 			if (child != sdata && child->vif.mbssid_tx_vif == &sdata->vif) {
 				child->vif.bss_conf.he_bss_color.color = color;
 				child->vif.bss_conf.he_bss_color.enabled = enable;
-				ieee80211_bss_info_change_notify(child,
-								 BSS_CHANGED_HE_BSS_COLOR);
+				ieee80211_link_info_change_notify(child, 0,
+								  BSS_CHANGED_HE_BSS_COLOR);
 			}
 		}
 		mutex_unlock(&sdata->local->iflist_mtx);
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 67131ca3f649..5d8b49f20198 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -799,8 +799,7 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
 
 	if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
 	    sdata->vif.type != NL80211_IFTYPE_MONITOR)
-		ieee80211_bss_info_change_notify(sdata,
-						 BSS_CHANGED_IDLE);
+		ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
 
 	ieee80211_check_fast_xmit_iface(sdata);
 
@@ -1188,7 +1187,7 @@ ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
 	ieee80211_recalc_radar_chanctx(local, new_ctx);
 
 	if (changed)
-		ieee80211_bss_info_change_notify(sdata, changed);
+		ieee80211_link_info_change_notify(sdata, 0, changed);
 
 out:
 	ieee80211_vif_chanctx_reservation_complete(sdata);
@@ -1533,8 +1532,8 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 			ieee80211_vif_update_chandef(sdata,
 						     &sdata->deflink.reserved_chandef);
 			if (changed)
-				ieee80211_bss_info_change_notify(sdata,
-								 changed);
+				ieee80211_link_info_change_notify(sdata, 0,
+								  changed);
 
 			ieee80211_recalc_txpower(sdata, false);
 		}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index fd2882348211..15ab8d00815b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -147,10 +147,27 @@ static inline int drv_config(struct ieee80211_local *local, u32 changed)
 	return ret;
 }
 
-static inline void drv_bss_info_changed(struct ieee80211_local *local,
-					struct ieee80211_sub_if_data *sdata,
-					struct ieee80211_bss_conf *info,
-					u32 changed)
+static inline void drv_vif_cfg_changed(struct ieee80211_local *local,
+				       struct ieee80211_sub_if_data *sdata,
+				       u64 changed)
+{
+	might_sleep();
+
+	if (!check_sdata_in_driver(sdata))
+		return;
+
+	trace_drv_vif_cfg_changed(local, sdata, changed);
+	if (local->ops->vif_cfg_changed)
+		local->ops->vif_cfg_changed(&local->hw, &sdata->vif, changed);
+	else if (local->ops->bss_info_changed)
+		local->ops->bss_info_changed(&local->hw, &sdata->vif,
+					     &sdata->vif.bss_conf, changed);
+	trace_drv_return_void(local);
+}
+
+static inline void drv_link_info_changed(struct ieee80211_local *local,
+					 struct ieee80211_sub_if_data *sdata,
+					 int link_id, u64 changed)
 {
 	might_sleep();
 
@@ -172,9 +189,13 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
 	if (!check_sdata_in_driver(sdata))
 		return;
 
-	trace_drv_bss_info_changed(local, sdata, info, changed);
-	if (local->ops->bss_info_changed)
-		local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed);
+	trace_drv_link_info_changed(local, sdata, link_id, changed);
+	if (local->ops->link_info_changed)
+		local->ops->link_info_changed(&local->hw, &sdata->vif,
+					      link_id, changed);
+	else if (local->ops->bss_info_changed)
+		local->ops->bss_info_changed(&local->hw, &sdata->vif,
+					     &sdata->vif.bss_conf, changed);
 	trace_drv_return_void(local);
 }
 
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 066f7c5adeec..3b68e9f4345b 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1851,7 +1851,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
 		| IEEE80211_HT_PARAM_RIFS_MODE;
 
 	changed |= BSS_CHANGED_HT | BSS_CHANGED_MCAST_RATE;
-	ieee80211_bss_info_change_notify(sdata, changed);
+	ieee80211_link_info_change_notify(sdata, 0, changed);
 
 	sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
 	sdata->deflink.needed_rx_chains = local->rx_chains;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f0a8bb444033..20153957cdee 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1836,7 +1836,11 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
 int ieee80211_hw_config(struct ieee80211_local *local, u32 changed);
 void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
 void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
-				      u32 changed);
+				      u64 changed);
+void ieee80211_vif_cfg_change_notify(struct ieee80211_sub_if_data *sdata,
+				     u64 changed);
+void ieee80211_link_info_change_notify(struct ieee80211_sub_if_data *sdata,
+				       int link_id, u64 changed);
 void ieee80211_configure_filter(struct ieee80211_local *local);
 u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
 
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2ee34d898821..978dfa48e098 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -80,7 +80,8 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
 {
 	if (__ieee80211_recalc_txpower(sdata) ||
 	    (update_bss && ieee80211_sdata_running(sdata)))
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
+		ieee80211_link_info_change_notify(sdata, 0,
+						  BSS_CHANGED_TXPOWER);
 }
 
 static u32 __ieee80211_idle_off(struct ieee80211_local *local)
@@ -1281,7 +1282,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 		if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
 		    sdata->vif.type != NL80211_IFTYPE_NAN)
 			changed |= ieee80211_reset_erp_info(sdata);
-		ieee80211_bss_info_change_notify(sdata, changed);
+		ieee80211_link_info_change_notify(sdata, 0, changed);
 
 		switch (sdata->vif.type) {
 		case NL80211_IFTYPE_STATION:
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0c81ae492df4..6165b90bf0e2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -199,15 +199,84 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 	return ret;
 }
 
+#define BSS_CHANGED_VIF_CFG_FLAGS (BSS_CHANGED_ASSOC |\
+				   BSS_CHANGED_IDLE |\
+				   BSS_CHANGED_IBSS |\
+				   BSS_CHANGED_ARP_FILTER |\
+				   BSS_CHANGED_SSID)
+
 void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
-				      u32 changed)
+				      u64 changed)
 {
 	struct ieee80211_local *local = sdata->local;
 
+	might_sleep();
+
 	if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 		return;
 
-	drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
+	if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON |
+				    BSS_CHANGED_BEACON_ENABLED) &&
+			 sdata->vif.type != NL80211_IFTYPE_AP &&
+			 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+			 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
+			 sdata->vif.type != NL80211_IFTYPE_OCB))
+		return;
+
+	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
+			 sdata->vif.type == NL80211_IFTYPE_NAN ||
+			 (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+			  !sdata->vif.bss_conf.mu_mimo_owner &&
+			  !(changed & BSS_CHANGED_TXPOWER))))
+		return;
+
+	if (!check_sdata_in_driver(sdata))
+		return;
+
+	if (changed & BSS_CHANGED_VIF_CFG_FLAGS) {
+		trace_drv_vif_cfg_changed(local, sdata, changed);
+		if (local->ops->vif_cfg_changed)
+			local->ops->vif_cfg_changed(&local->hw, &sdata->vif, changed);
+	}
+
+	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
+		/* FIXME: should be for each link */
+		trace_drv_link_info_changed(local, sdata, 0, changed);
+		if (local->ops->link_info_changed)
+			local->ops->link_info_changed(&local->hw, &sdata->vif,
+						      0, changed);
+	}
+
+	if (local->ops->bss_info_changed)
+		local->ops->bss_info_changed(&local->hw, &sdata->vif,
+					     &sdata->vif.bss_conf, changed);
+	trace_drv_return_void(local);
+}
+
+void ieee80211_vif_cfg_change_notify(struct ieee80211_sub_if_data *sdata,
+				     u64 changed)
+{
+	struct ieee80211_local *local = sdata->local;
+
+	WARN_ON_ONCE(changed & ~BSS_CHANGED_VIF_CFG_FLAGS);
+
+	if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+		return;
+
+	drv_vif_cfg_changed(local, sdata, changed);
+}
+
+void ieee80211_link_info_change_notify(struct ieee80211_sub_if_data *sdata,
+				       int link_id, u64 changed)
+{
+	struct ieee80211_local *local = sdata->local;
+
+	WARN_ON_ONCE(changed & BSS_CHANGED_VIF_CFG_FLAGS);
+
+	if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+		return;
+
+	drv_link_info_changed(local, sdata, link_id, changed);
 }
 
 u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata)
@@ -387,8 +456,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
 
 	/* Configure driver only if associated (which also implies it is up) */
 	if (ifmgd->associated)
-		ieee80211_bss_info_change_notify(sdata,
-						 BSS_CHANGED_ARP_FILTER);
+		ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_ARP_FILTER);
 
 	sdata_unlock(sdata);
 
@@ -557,6 +625,10 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
 	if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
 		return NULL;
 
+	if (WARN_ON(!!ops->link_info_changed != !!ops->vif_cfg_changed ||
+		    (ops->link_info_changed && ops->bss_info_changed)))
+		return NULL;
+
 	/* check all or no channel context operations exist */
 	i = !!ops->add_chanctx + !!ops->remove_chanctx +
 	    !!ops->change_chanctx + !!ops->assign_vif_chanctx +
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index f60e257cba95..13722a7f2254 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1057,7 +1057,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
 	}
 
 	ieee80211_recalc_dtim(local, sdata);
-	ieee80211_bss_info_change_notify(sdata, changed);
+	ieee80211_link_info_change_notify(sdata, 0, changed);
 
 	netif_carrier_on(sdata->dev);
 	return 0;
@@ -1081,7 +1081,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
 	sdata->vif.bss_conf.enable_beacon = false;
 	sdata->beacon_rate_set = false;
 	clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
+	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_BEACON_ENABLED);
 
 	/* remove beacon */
 	bcn = rcu_dereference_protected(ifmsh->beacon,
@@ -1581,7 +1581,7 @@ static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata)
 		if (ieee80211_mesh_rebuild_beacon(sdata))
 			return;
 
-	ieee80211_bss_info_change_notify(sdata, changed);
+	ieee80211_link_info_change_notify(sdata, 0, changed);
 }
 
 void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index fd1b97e1e990..e172bdfe9b0a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1835,7 +1835,7 @@ void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata)
 
 	if (sdata->vif.bss_conf.ps != ps_allowed) {
 		sdata->vif.bss_conf.ps = ps_allowed;
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_PS);
+		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_PS);
 	}
 }
 
@@ -2031,7 +2031,7 @@ __ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
 void ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
 {
 	if (__ieee80211_sta_handle_tspec_ac_params(sdata))
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
+		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_QOS);
 }
 
 static void ieee80211_sta_handle_tspec_ac_params_wk(struct work_struct *work)
@@ -2920,7 +2920,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
 		sta_info_destroy_addr(sdata, auth_data->bss->bssid);
 
 		eth_zero_addr(sdata->deflink.u.mgd.bssid);
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_BSSID);
 		sdata->u.mgd.flags = 0;
 		mutex_lock(&sdata->local->mtx);
 		ieee80211_vif_release_channel(sdata);
@@ -2949,7 +2949,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
 		sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
 
 		eth_zero_addr(sdata->deflink.u.mgd.bssid);
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_BSSID);
 		sdata->u.mgd.flags = 0;
 		sdata->vif.bss_conf.mu_mimo_owner = false;
 
@@ -4387,7 +4387,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 					       elems->pwr_constr_elem,
 					       elems->cisco_dtpc_elem);
 
-	ieee80211_bss_info_change_notify(sdata, changed);
+	ieee80211_link_info_change_notify(sdata, 0, changed);
 free:
 	kfree(elems);
 }
@@ -5697,7 +5697,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
 		 * tell driver about BSSID, basic rates and timing
 		 * this was set up above, before setting the channel
 		 */
-		ieee80211_bss_info_change_notify(sdata,
+		ieee80211_link_info_change_notify(sdata, 0,
 			BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES |
 			BSS_CHANGED_BEACON_INT);
 
@@ -5865,7 +5865,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 
  err_clear:
 	eth_zero_addr(sdata->deflink.u.mgd.bssid);
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_BSSID);
 	ifmgd->auth_data = NULL;
 	mutex_lock(&sdata->local->mtx);
 	ieee80211_vif_release_channel(sdata);
@@ -6212,7 +6212,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	return 0;
  err_clear:
 	eth_zero_addr(sdata->deflink.u.mgd.bssid);
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_BSSID);
 	ifmgd->assoc_data = NULL;
  err_free:
 	kfree(assoc_data);
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 6cd3df1eb687..2ed4e2325914 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -118,8 +118,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
 			set_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
 				&sdata->state);
 			sdata->vif.bss_conf.enable_beacon = false;
-			ieee80211_bss_info_change_notify(
-				sdata, BSS_CHANGED_BEACON_ENABLED);
+			ieee80211_link_info_change_notify(
+				sdata, 0, BSS_CHANGED_BEACON_ENABLED);
 		}
 
 		if (sdata->vif.type == NL80211_IFTYPE_STATION &&
@@ -155,8 +155,8 @@ void ieee80211_offchannel_return(struct ieee80211_local *local)
 		if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED,
 				       &sdata->state)) {
 			sdata->vif.bss_conf.enable_beacon = true;
-			ieee80211_bss_info_change_notify(
-				sdata, BSS_CHANGED_BEACON_ENABLED);
+			ieee80211_link_info_change_notify(
+				sdata, 0, BSS_CHANGED_BEACON_ENABLED);
 		}
 	}
 	mutex_unlock(&local->iflist_mtx);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 115efa830673..9a70d846d0dd 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -630,7 +630,7 @@ ieee80211_recalc_p2p_go_ps_allowed(struct ieee80211_sub_if_data *sdata)
 
 	if (allow_p2p_go_ps != sdata->vif.bss_conf.allow_p2p_go_ps) {
 		sdata->vif.bss_conf.allow_p2p_go_ps = allow_p2p_go_ps;
-		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_P2P_PS);
+		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_P2P_PS);
 	}
 }
 
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 8a2ec9c31240..11a3b950b490 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -1335,7 +1335,7 @@ iee80211_tdls_recalc_ht_protection(struct ieee80211_sub_if_data *sdata,
 		return;
 
 	sdata->vif.bss_conf.ht_operation_mode = opmode;
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
+	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_HT);
 }
 
 int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 74ef7e71e1ef..7284f0bf8a99 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -390,22 +390,71 @@ TRACE_EVENT(drv_config,
 	)
 );
 
-TRACE_EVENT(drv_bss_info_changed,
+TRACE_EVENT(drv_vif_cfg_changed,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata,
-		 struct ieee80211_bss_conf *info,
-		 u32 changed),
+		 u64 changed),
 
-	TP_ARGS(local, sdata, info, changed),
+	TP_ARGS(local, sdata, changed),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
 		VIF_ENTRY
-		__field(u32, changed)
+		__field(u64, changed)
 		__field(bool, assoc)
 		__field(bool, ibss_joined)
 		__field(bool, ibss_creator)
 		__field(u16, aid)
+		__dynamic_array(u32, arp_addr_list,
+				sdata->vif.cfg.arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
+					IEEE80211_BSS_ARP_ADDR_LIST_LEN :
+					sdata->vif.cfg.arp_addr_cnt)
+		__field(int, arp_addr_cnt)
+		__dynamic_array(u8, ssid, sdata->vif.cfg.ssid_len)
+		__field(int, s1g)
+		__field(bool, idle)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		VIF_ASSIGN;
+		__entry->changed = changed;
+		__entry->aid = sdata->vif.cfg.aid;
+		__entry->assoc = sdata->vif.cfg.assoc;
+		__entry->ibss_joined = sdata->vif.cfg.ibss_joined;
+		__entry->ibss_creator = sdata->vif.cfg.ibss_creator;
+
+		__entry->arp_addr_cnt = sdata->vif.cfg.arp_addr_cnt;
+		memcpy(__get_dynamic_array(arp_addr_list),
+		       sdata->vif.cfg.arp_addr_list,
+		       sizeof(u32) * (sdata->vif.cfg.arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
+					IEEE80211_BSS_ARP_ADDR_LIST_LEN :
+					sdata->vif.cfg.arp_addr_cnt));
+		memcpy(__get_dynamic_array(ssid),
+		       sdata->vif.cfg.ssid,
+		       sdata->vif.cfg.ssid_len);
+		__entry->s1g = sdata->vif.cfg.s1g;
+		__entry->idle = sdata->vif.cfg.idle;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT  VIF_PR_FMT " changed:%#llx",
+		LOCAL_PR_ARG, VIF_PR_ARG, (unsigned long long)__entry->changed
+	)
+);
+
+TRACE_EVENT(drv_link_info_changed,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 int link_id, u64 changed),
+
+	TP_ARGS(local, sdata, link_id, changed),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		VIF_ENTRY
+		__field(u64, changed)
+		__field(int, link_id)
 		__field(bool, cts)
 		__field(bool, shortpre)
 		__field(bool, shortslot)
@@ -424,15 +473,8 @@ TRACE_EVENT(drv_bss_info_changed,
 		__field(u32, channel_width)
 		__field(u32, channel_cfreq1)
 		__field(u32, channel_cfreq1_offset)
-		__dynamic_array(u32, arp_addr_list,
-				sdata->vif.cfg.arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
-					IEEE80211_BSS_ARP_ADDR_LIST_LEN :
-					sdata->vif.cfg.arp_addr_cnt)
-		__field(int, arp_addr_cnt)
 		__field(bool, qos)
-		__field(bool, idle)
 		__field(bool, ps)
-		__dynamic_array(u8, ssid, sdata->vif.cfg.ssid_len)
 		__field(bool, hidden_ssid)
 		__field(int, txpower)
 		__field(u8, p2p_oppps_ctwindow)
@@ -442,49 +484,37 @@ TRACE_EVENT(drv_bss_info_changed,
 		LOCAL_ASSIGN;
 		VIF_ASSIGN;
 		__entry->changed = changed;
-		__entry->aid = sdata->vif.cfg.aid;
-		__entry->assoc = sdata->vif.cfg.assoc;
-		__entry->ibss_joined = sdata->vif.cfg.ibss_joined;
-		__entry->ibss_creator = sdata->vif.cfg.ibss_creator;
-		__entry->shortpre = info->use_short_preamble;
-		__entry->cts = info->use_cts_prot;
-		__entry->shortslot = info->use_short_slot;
-		__entry->enable_beacon = info->enable_beacon;
-		__entry->dtimper = info->dtim_period;
-		__entry->bcnint = info->beacon_int;
-		__entry->assoc_cap = info->assoc_capability;
-		__entry->sync_tsf = info->sync_tsf;
-		__entry->sync_device_ts = info->sync_device_ts;
-		__entry->sync_dtim_count = info->sync_dtim_count;
-		__entry->basic_rates = info->basic_rates;
-		memcpy(__entry->mcast_rate, info->mcast_rate,
+		__entry->link_id = link_id;
+		__entry->shortpre = sdata->vif.bss_conf.use_short_preamble;
+		__entry->cts = sdata->vif.bss_conf.use_cts_prot;
+		__entry->shortslot = sdata->vif.bss_conf.use_short_slot;
+		__entry->enable_beacon = sdata->vif.bss_conf.enable_beacon;
+		__entry->dtimper = sdata->vif.bss_conf.dtim_period;
+		__entry->bcnint = sdata->vif.bss_conf.beacon_int;
+		__entry->assoc_cap = sdata->vif.bss_conf.assoc_capability;
+		__entry->sync_tsf = sdata->vif.bss_conf.sync_tsf;
+		__entry->sync_device_ts = sdata->vif.bss_conf.sync_device_ts;
+		__entry->sync_dtim_count = sdata->vif.bss_conf.sync_dtim_count;
+		__entry->basic_rates = sdata->vif.bss_conf.basic_rates;
+		memcpy(__entry->mcast_rate, sdata->vif.bss_conf.mcast_rate,
 		       sizeof(__entry->mcast_rate));
-		__entry->ht_operation_mode = info->ht_operation_mode;
-		__entry->cqm_rssi_thold = info->cqm_rssi_thold;
-		__entry->cqm_rssi_hyst = info->cqm_rssi_hyst;
-		__entry->channel_width = info->chandef.width;
-		__entry->channel_cfreq1 = info->chandef.center_freq1;
-		__entry->channel_cfreq1_offset = info->chandef.freq1_offset;
-		__entry->arp_addr_cnt = sdata->vif.cfg.arp_addr_cnt;
-		memcpy(__get_dynamic_array(arp_addr_list),
-		       sdata->vif.cfg.arp_addr_list,
-		       sizeof(u32) * (sdata->vif.cfg.arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
-					IEEE80211_BSS_ARP_ADDR_LIST_LEN :
-					sdata->vif.cfg.arp_addr_cnt));
-		__entry->qos = info->qos;
-		__entry->idle = sdata->vif.cfg.idle;
-		__entry->ps = info->ps;
-		memcpy(__get_dynamic_array(ssid),
-		       sdata->vif.cfg.ssid,
-		       sdata->vif.cfg.ssid_len);
-		__entry->hidden_ssid = info->hidden_ssid;
-		__entry->txpower = info->txpower;
-		__entry->p2p_oppps_ctwindow = info->p2p_noa_attr.oppps_ctwindow;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT  VIF_PR_FMT " changed:%#x",
-		LOCAL_PR_ARG, VIF_PR_ARG, __entry->changed
+		__entry->ht_operation_mode = sdata->vif.bss_conf.ht_operation_mode;
+		__entry->cqm_rssi_thold = sdata->vif.bss_conf.cqm_rssi_thold;
+		__entry->cqm_rssi_hyst = sdata->vif.bss_conf.cqm_rssi_hyst;
+		__entry->channel_width = sdata->vif.bss_conf.chandef.width;
+		__entry->channel_cfreq1 = sdata->vif.bss_conf.chandef.center_freq1;
+		__entry->channel_cfreq1_offset = sdata->vif.bss_conf.chandef.freq1_offset;
+		__entry->qos = sdata->vif.bss_conf.qos;
+		__entry->ps = sdata->vif.bss_conf.ps;
+		__entry->hidden_ssid = sdata->vif.bss_conf.hidden_ssid;
+		__entry->txpower = sdata->vif.bss_conf.txpower;
+		__entry->p2p_oppps_ctwindow = sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT  VIF_PR_FMT " link_id:%d, changed:%#llx",
+		LOCAL_PR_ARG, VIF_PR_ARG, __entry->link_id,
+		(unsigned long long)__entry->changed
 	)
 );
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 9cbc09e6d84e..2a279dc3e457 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1699,8 +1699,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
 	    sdata->vif.type != NL80211_IFTYPE_NAN) {
 		sdata->vif.bss_conf.qos = enable_qos;
 		if (bss_notify)
-			ieee80211_bss_info_change_notify(sdata,
-							 BSS_CHANGED_QOS);
+			ieee80211_link_info_change_notify(sdata, 0,
+							  BSS_CHANGED_QOS);
 	}
 }
 
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index ac97584b3a0b..7daca8352deb 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -665,7 +665,7 @@ void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
 	       mgmt->u.action.u.vht_group_notif.position,
 	       WLAN_USER_POSITION_LEN);
 
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MU_GROUPS);
+	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_MU_GROUPS);
 }
 
 void ieee80211_update_mu_groups(struct ieee80211_vif *vif,
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 02/15] mac80211: add per-link configuration pointer
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
  2022-06-01  7:39 ` [PATCH 01/15] mac80211: split bss_info_changed method Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 03/15] mac80211: pass link ID where already present Johannes Berg
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Add pointers so we can start using link_id throughout the
code, even if for now only link ID 0 is valid, pointing
to the "built-in" bss_conf, which is used by drivers that
are not aware of MLD.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h     |  3 +++
 net/mac80211/ieee80211_i.h |  1 +
 net/mac80211/iface.c       | 23 +++++++++++++++++++++--
 3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 831f14b7ca69..e4868bccb446 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1739,6 +1739,8 @@ struct ieee80211_vif_cfg {
  * @cfg: vif configuration, see &struct ieee80211_vif_cfg
  * @bss_conf: BSS configuration for this interface, either our own
  *	or the BSS we're associated to
+ * @link_conf: in case of MLD, the per-link BSS configuration,
+ *	indexed by link ID
  * @addr: address of this interface
  * @p2p: indicates whether this AP or STA interface is a p2p
  *	interface, i.e. a GO or p2p-sta respectively
@@ -1773,6 +1775,7 @@ struct ieee80211_vif {
 	enum nl80211_iftype type;
 	struct ieee80211_vif_cfg cfg;
 	struct ieee80211_bss_conf bss_conf;
+	struct ieee80211_bss_conf *link_conf[IEEE80211_MLD_MAX_NUM_LINKS];
 	u8 addr[ETH_ALEN] __aligned(2);
 	bool p2p;
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 20153957cdee..397b111f006d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1031,6 +1031,7 @@ struct ieee80211_sub_if_data {
 	} u;
 
 	struct ieee80211_link_data deflink;
+	struct ieee80211_link_data *link[IEEE80211_MLD_MAX_NUM_LINKS];
 
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 978dfa48e098..04ee525394e9 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1012,6 +1012,23 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
 	sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
 }
 
+static void ieee80211_sdata_init(struct ieee80211_local *local,
+				 struct ieee80211_sub_if_data *sdata)
+{
+	sdata->local = local;
+
+	/*
+	 * Initialize the default link, so we can use link_id 0 for non-MLD,
+	 * and that continues to work for non-MLD-aware drivers that use just
+	 * vif.bss_conf instead of vif.link_conf.
+	 *
+	 * Note that we never change this, so if link ID 0 isn't used in an
+	 * MLD connection, we get a separate allocation for it.
+	 */
+	sdata->vif.link_conf[0] = &sdata->vif.bss_conf;
+	sdata->link[0] = &sdata->deflink;
+}
+
 int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 {
 	struct ieee80211_sub_if_data *sdata;
@@ -1031,12 +1048,13 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 		return -ENOMEM;
 
 	/* set up data */
-	sdata->local = local;
 	sdata->vif.type = NL80211_IFTYPE_MONITOR;
 	snprintf(sdata->name, IFNAMSIZ, "%s-monitor",
 		 wiphy_name(local->hw.wiphy));
 	sdata->wdev.iftype = NL80211_IFTYPE_MONITOR;
 
+	ieee80211_sdata_init(local, sdata);
+
 	ieee80211_set_default_queues(sdata);
 
 	ret = drv_add_interface(local, sdata);
@@ -2074,7 +2092,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
 	/* initialise type-independent data */
 	sdata->wdev.wiphy = local->hw.wiphy;
-	sdata->local = local;
+
+	ieee80211_sdata_init(local, sdata);
 
 	ieee80211_init_frag_cache(&sdata->frags);
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 03/15] mac80211: pass link ID where already present
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
  2022-06-01  7:39 ` [PATCH 01/15] mac80211: split bss_info_changed method Johannes Berg
  2022-06-01  7:39 ` [PATCH 02/15] mac80211: add per-link configuration pointer Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 04/15] mac80211: make channel context code MLO-aware Johannes Berg
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

In a few cases we already have the link ID in the APIs,
pass it already even if it cannot be non-zero yet.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ffd26db89f33..b9a03548c89a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1338,7 +1338,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
 		err |= BSS_CHANGED_HE_BSS_COLOR;
 	}
 
-	ieee80211_link_info_change_notify(sdata, 0, err);
+	ieee80211_link_info_change_notify(sdata, params->link_id, err);
 	return 0;
 }
 
@@ -1419,7 +1419,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
 	sdata->beacon_rate_set = false;
 	sdata->vif.cfg.ssid_len = 0;
 	clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
-	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_BEACON_ENABLED);
+	ieee80211_link_info_change_notify(sdata, link_id,
+					  BSS_CHANGED_BEACON_ENABLED);
 
 	if (sdata->wdev.cac_started) {
 		chandef = sdata->vif.bss_conf.chandef;
@@ -3985,7 +3986,7 @@ static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
 
 	ret = ieee80211_vif_change_bandwidth(sdata, chandef, &changed);
 	if (ret == 0)
-		ieee80211_link_info_change_notify(sdata, 0, changed);
+		ieee80211_link_info_change_notify(sdata, link_id, changed);
 
 	return ret;
 }
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 04/15] mac80211: make channel context code MLO-aware
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (2 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 03/15] mac80211: pass link ID where already present Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2023-02-14  7:57     ` Wen Gong
  2022-06-01  7:39 ` [PATCH 05/15] mac80211: remove sta_info_tx_streams() Johannes Berg
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Make the channel context code MLO aware, along with some
functions that it uses, so that the chan.c file is now
MLD-clean and no longer uses deflink/bss_conf/etc.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/ath/ath10k/mac.c         |   2 +
 drivers/net/wireless/ath/ath11k/mac.c         |   2 +
 drivers/net/wireless/ath/ath9k/main.c         |   2 +
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |   2 +
 drivers/net/wireless/mac80211_hwsim.c         |   2 +
 drivers/net/wireless/silabs/wfx/sta.c         |   2 +
 drivers/net/wireless/silabs/wfx/sta.h         |   2 +
 drivers/net/wireless/ti/wlcore/main.c         |   2 +
 include/net/mac80211.h                        |   4 +
 net/mac80211/cfg.c                            |  52 +-
 net/mac80211/chan.c                           | 642 +++++++++++-------
 net/mac80211/debug.h                          |  14 +
 net/mac80211/driver-ops.h                     |   8 +-
 net/mac80211/eht.c                            |   4 +-
 net/mac80211/he.c                             |   6 +-
 net/mac80211/ibss.c                           |   8 +-
 net/mac80211/ieee80211_i.h                    |  51 +-
 net/mac80211/iface.c                          |  15 +-
 net/mac80211/mesh_plink.c                     |   4 +-
 net/mac80211/mlme.c                           |  28 +-
 net/mac80211/ocb.c                            |   6 +-
 net/mac80211/rate.c                           |   8 +-
 net/mac80211/rate.h                           |   7 +-
 net/mac80211/rx.c                             |   8 +-
 net/mac80211/tdls.c                           |   4 +-
 net/mac80211/trace.h                          |  17 +-
 net/mac80211/util.c                           |  39 +-
 net/mac80211/vht.c                            |  36 +-
 28 files changed, 586 insertions(+), 391 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index bc0135868792..b9155e7b910a 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -8885,6 +8885,7 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
 static int
 ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
+				 unsigned int link_id,
 				 struct ieee80211_chanctx_conf *ctx)
 {
 	struct ath10k *ar = hw->priv;
@@ -8964,6 +8965,7 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 static void
 ath10k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif,
+				   unsigned int link_id,
 				   struct ieee80211_chanctx_conf *ctx)
 {
 	struct ath10k *ar = hw->priv;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index be102357317b..42c4584b4df1 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -7071,6 +7071,7 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
 static int
 ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
+				 unsigned int link_id,
 				 struct ieee80211_chanctx_conf *ctx)
 {
 	struct ath11k *ar = hw->priv;
@@ -7160,6 +7161,7 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 static void
 ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif,
+				   unsigned int link_id,
 				   struct ieee80211_chanctx_conf *ctx)
 {
 	struct ath11k *ar = hw->priv;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 729f8ee9644d..c3d5d9795424 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2596,6 +2596,7 @@ static void ath9k_change_chanctx(struct ieee80211_hw *hw,
 
 static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
+				    unsigned int link_id,
 				    struct ieee80211_chanctx_conf *conf)
 {
 	struct ath_softc *sc = hw->priv;
@@ -2627,6 +2628,7 @@ static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
 
 static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
+				       unsigned int link_id,
 				       struct ieee80211_chanctx_conf *conf)
 {
 	struct ath_softc *sc = hw->priv;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 586208506275..5d3cedc146be 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -4235,6 +4235,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
 }
 static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
 				      struct ieee80211_vif *vif,
+				      unsigned int link_id,
 				      struct ieee80211_chanctx_conf *ctx)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -4308,6 +4309,7 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
 
 static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
 					 struct ieee80211_vif *vif,
+					 unsigned int link_id,
 					 struct ieee80211_chanctx_conf *ctx)
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 1bd96b504956..0918f9dfec00 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2723,6 +2723,7 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
 
 static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw,
 					     struct ieee80211_vif *vif,
+					     unsigned int link_id,
 					     struct ieee80211_chanctx_conf *ctx)
 {
 	hwsim_check_magic(vif);
@@ -2733,6 +2734,7 @@ static int mac80211_hwsim_assign_vif_chanctx(struct ieee80211_hw *hw,
 
 static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw,
 						struct ieee80211_vif *vif,
+						unsigned int link_id,
 						struct ieee80211_chanctx_conf *ctx)
 {
 	hwsim_check_magic(vif);
diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c
index 6fb4ba1282c9..c47b9150097d 100644
--- a/drivers/net/wireless/silabs/wfx/sta.c
+++ b/drivers/net/wireless/silabs/wfx/sta.c
@@ -680,6 +680,7 @@ void wfx_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *
 }
 
 int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			   unsigned int link_id,
 			   struct ieee80211_chanctx_conf *conf)
 {
 	struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
@@ -692,6 +693,7 @@ int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 }
 
 void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			      unsigned int link_id,
 			      struct ieee80211_chanctx_conf *conf)
 {
 	struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
diff --git a/drivers/net/wireless/silabs/wfx/sta.h b/drivers/net/wireless/silabs/wfx/sta.h
index d9c6bd632b20..3109d257fe94 100644
--- a/drivers/net/wireless/silabs/wfx/sta.h
+++ b/drivers/net/wireless/silabs/wfx/sta.h
@@ -48,8 +48,10 @@ int wfx_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf
 void wfx_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf);
 void wfx_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *conf, u32 changed);
 int wfx_assign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			   unsigned int link_id,
 			   struct ieee80211_chanctx_conf *conf);
 void wfx_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			      unsigned int link_id,
 			      struct ieee80211_chanctx_conf *conf);
 
 /* Hardware API Callbacks */
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index d365bdce2a10..b476f244a20e 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4701,6 +4701,7 @@ static void wlcore_op_change_chanctx(struct ieee80211_hw *hw,
 
 static int wlcore_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 					struct ieee80211_vif *vif,
+					unsigned int link_id,
 					struct ieee80211_chanctx_conf *ctx)
 {
 	struct wl1271 *wl = hw->priv;
@@ -4751,6 +4752,7 @@ static int wlcore_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 
 static void wlcore_op_unassign_vif_chanctx(struct ieee80211_hw *hw,
 					   struct ieee80211_vif *vif,
+					   unsigned int link_id,
 					   struct ieee80211_chanctx_conf *ctx)
 {
 	struct wl1271 *wl = hw->priv;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e4868bccb446..4b3d19d88954 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -261,11 +261,13 @@ enum ieee80211_chanctx_switch_mode {
  * done.
  *
  * @vif: the vif that should be switched from old_ctx to new_ctx
+ * @link_id: the link ID that's switching
  * @old_ctx: the old context to which the vif was assigned
  * @new_ctx: the new context to which the vif must be assigned
  */
 struct ieee80211_vif_chanctx_switch {
 	struct ieee80211_vif *vif;
+	unsigned int link_id;
 	struct ieee80211_chanctx_conf *old_ctx;
 	struct ieee80211_chanctx_conf *new_ctx;
 };
@@ -4262,9 +4264,11 @@ struct ieee80211_ops {
 			       u32 changed);
 	int (*assign_vif_chanctx)(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
+				  unsigned int link_id,
 				  struct ieee80211_chanctx_conf *ctx);
 	void (*unassign_vif_chanctx)(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
+				     unsigned int link_id,
 				     struct ieee80211_chanctx_conf *ctx);
 	int (*switch_vif_chanctx)(struct ieee80211_hw *hw,
 				  struct ieee80211_vif_chanctx_switch *vifs,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b9a03548c89a..e76565cb6292 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -844,9 +844,10 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
 		sdata = wiphy_dereference(local->hw.wiphy,
 					  local->monitor_sdata);
 		if (sdata) {
-			ieee80211_vif_release_channel(sdata);
-			ret = ieee80211_vif_use_channel(sdata, chandef,
-					IEEE80211_CHANCTX_EXCLUSIVE);
+			ieee80211_link_release_channel(sdata->link[0]);
+			ret = ieee80211_link_use_channel(sdata->link[0],
+							 chandef,
+							 IEEE80211_CHANCTX_EXCLUSIVE);
 		}
 	} else if (local->open_count == local->monitors) {
 		local->_oper_chandef = *chandef;
@@ -1187,10 +1188,12 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	mutex_lock(&local->mtx);
-	err = ieee80211_vif_use_channel(sdata, &params->chandef,
-					IEEE80211_CHANCTX_SHARED);
+	err = ieee80211_link_use_channel(sdata->link[params->beacon.link_id],
+					 &params->chandef,
+					 IEEE80211_CHANCTX_SHARED);
 	if (!err)
-		ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
+		ieee80211_link_copy_chanctx_to_vlans(sdata->link[params->beacon.link_id],
+						     false);
 	mutex_unlock(&local->mtx);
 	if (err) {
 		sdata->vif.bss_conf.beacon_int = prev_beacon_int;
@@ -1300,7 +1303,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 
 error:
 	mutex_lock(&local->mtx);
-	ieee80211_vif_release_channel(sdata);
+	ieee80211_link_release_channel(sdata->link[params->beacon.link_id]);
 	mutex_unlock(&local->mtx);
 
 	return err;
@@ -1437,8 +1440,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
 	ieee80211_purge_tx_queue(&local->hw, &sdata->u.ap.ps.bc_buf);
 
 	mutex_lock(&local->mtx);
-	ieee80211_vif_copy_chanctx_to_vlans(sdata, true);
-	ieee80211_vif_release_channel(sdata);
+	ieee80211_link_copy_chanctx_to_vlans(sdata->link[link_id], true);
+	ieee80211_link_release_channel(sdata->link[link_id]);
 	mutex_unlock(&local->mtx);
 
 	return 0;
@@ -2405,8 +2408,8 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
 	sdata->deflink.needed_rx_chains = sdata->local->rx_chains;
 
 	mutex_lock(&sdata->local->mtx);
-	err = ieee80211_vif_use_channel(sdata, &setup->chandef,
-					IEEE80211_CHANCTX_SHARED);
+	err = ieee80211_link_use_channel(sdata->link[0], &setup->chandef,
+					 IEEE80211_CHANCTX_SHARED);
 	mutex_unlock(&sdata->local->mtx);
 	if (err)
 		return err;
@@ -2420,7 +2423,7 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
 
 	ieee80211_stop_mesh(sdata);
 	mutex_lock(&sdata->local->mtx);
-	ieee80211_vif_release_channel(sdata);
+	ieee80211_link_release_channel(sdata->link[0]);
 	kfree(sdata->u.mesh.ie);
 	mutex_unlock(&sdata->local->mtx);
 
@@ -3149,8 +3152,8 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
 	sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
 	sdata->deflink.needed_rx_chains = local->rx_chains;
 
-	err = ieee80211_vif_use_channel(sdata, chandef,
-					IEEE80211_CHANCTX_SHARED);
+	err = ieee80211_link_use_channel(sdata->link[0], chandef,
+					 IEEE80211_CHANCTX_SHARED);
 	if (err)
 		goto out_unlock;
 
@@ -3178,7 +3181,7 @@ static void ieee80211_end_cac(struct wiphy *wiphy,
 		cancel_delayed_work(&sdata->deflink.dfs_cac_timer_work);
 
 		if (sdata->wdev.cac_started) {
-			ieee80211_vif_release_channel(sdata);
+			ieee80211_link_release_channel(sdata->link[0]);
 			sdata->wdev.cac_started = false;
 		}
 	}
@@ -3382,7 +3385,7 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
 		if (sdata->deflink.reserved_ready)
 			return 0;
 
-		return ieee80211_vif_use_reserved_context(sdata);
+		return ieee80211_link_use_reserved_context(sdata->link[0]);
 	}
 
 	if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
@@ -3647,16 +3650,16 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 	if (err)
 		goto out;
 
-	err = ieee80211_vif_reserve_chanctx(sdata, &params->chandef,
-					    chanctx->mode,
-					    params->radar_required);
+	err = ieee80211_link_reserve_chanctx(sdata->link[0], &params->chandef,
+					     chanctx->mode,
+					     params->radar_required);
 	if (err)
 		goto out;
 
 	/* if reservation is invalid then this will fail */
 	err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0);
 	if (err) {
-		ieee80211_vif_unreserve_chanctx(sdata);
+		ieee80211_link_unreserve_chanctx(sdata->link[0]);
 		goto out;
 	}
 
@@ -3666,7 +3669,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
 
 	err = ieee80211_set_csa_beacon(sdata, params, &changed);
 	if (err) {
-		ieee80211_vif_unreserve_chanctx(sdata);
+		ieee80211_link_unreserve_chanctx(sdata->link[0]);
 		goto out;
 	}
 
@@ -3925,9 +3928,9 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
 	int ret = -ENODATA;
 
 	rcu_read_lock();
-	chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+	chanctx_conf = rcu_dereference(sdata->vif.link_conf[link_id]->chanctx_conf);
 	if (chanctx_conf) {
-		*chandef = sdata->vif.bss_conf.chandef;
+		*chandef = sdata->vif.link_conf[link_id]->chandef;
 		ret = 0;
 	} else if (local->open_count > 0 &&
 		   local->open_count == local->monitors &&
@@ -3984,7 +3987,8 @@ static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
 	int ret;
 	u32 changed = 0;
 
-	ret = ieee80211_vif_change_bandwidth(sdata, chandef, &changed);
+	ret = ieee80211_link_change_bandwidth(sdata->link[link_id], chandef,
+					      &changed);
 	if (ret == 0)
 		ieee80211_link_info_change_notify(sdata, link_id, changed);
 
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 5d8b49f20198..4f25660d0eeb 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -15,12 +15,12 @@
 static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
 					  struct ieee80211_chanctx *ctx)
 {
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_link_data *link;
 	int num = 0;
 
 	lockdep_assert_held(&local->chanctx_mtx);
 
-	list_for_each_entry(sdata, &ctx->assigned_vifs, assigned_chanctx_list)
+	list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list)
 		num++;
 
 	return num;
@@ -29,12 +29,12 @@ static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
 static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
 					  struct ieee80211_chanctx *ctx)
 {
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_link_data *link;
 	int num = 0;
 
 	lockdep_assert_held(&local->chanctx_mtx);
 
-	list_for_each_entry(sdata, &ctx->reserved_vifs, reserved_chanctx_list)
+	list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list)
 		num++;
 
 	return num;
@@ -67,12 +67,14 @@ static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local)
 }
 
 static struct ieee80211_chanctx *
-ieee80211_vif_get_chanctx(struct ieee80211_sub_if_data *sdata)
+ieee80211_vif_get_chanctx(struct ieee80211_sub_if_data *sdata,
+			  unsigned int link_id)
 {
+	struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
 	struct ieee80211_local *local __maybe_unused = sdata->local;
 	struct ieee80211_chanctx_conf *conf;
 
-	conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf,
+	conf = rcu_dereference_protected(link_conf->chanctx_conf,
 					 lockdep_is_held(&local->chanctx_mtx));
 	if (!conf)
 		return NULL;
@@ -80,21 +82,27 @@ ieee80211_vif_get_chanctx(struct ieee80211_sub_if_data *sdata)
 	return container_of(conf, struct ieee80211_chanctx, conf);
 }
 
+static struct ieee80211_chanctx *
+ieee80211_link_get_chanctx(struct ieee80211_link_data *link)
+{
+	return ieee80211_vif_get_chanctx(link->sdata, link->link_id);
+}
+
 static const struct cfg80211_chan_def *
 ieee80211_chanctx_reserved_chandef(struct ieee80211_local *local,
 				   struct ieee80211_chanctx *ctx,
 				   const struct cfg80211_chan_def *compat)
 {
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_link_data *link;
 
 	lockdep_assert_held(&local->chanctx_mtx);
 
-	list_for_each_entry(sdata, &ctx->reserved_vifs,
+	list_for_each_entry(link, &ctx->reserved_links,
 			    reserved_chanctx_list) {
 		if (!compat)
-			compat = &sdata->deflink.reserved_chandef;
+			compat = &link->reserved_chandef;
 
-		compat = cfg80211_chandef_compatible(&sdata->deflink.reserved_chandef,
+		compat = cfg80211_chandef_compatible(&link->reserved_chandef,
 						     compat);
 		if (!compat)
 			break;
@@ -108,20 +116,23 @@ ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
 				       struct ieee80211_chanctx *ctx,
 				       const struct cfg80211_chan_def *compat)
 {
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_link_data *link;
 
 	lockdep_assert_held(&local->chanctx_mtx);
 
-	list_for_each_entry(sdata, &ctx->assigned_vifs,
+	list_for_each_entry(link, &ctx->assigned_links,
 			    assigned_chanctx_list) {
-		if (sdata->deflink.reserved_chanctx != NULL)
+		struct ieee80211_bss_conf *link_conf =
+			link->sdata->vif.link_conf[link->link_id];
+
+		if (link->reserved_chanctx)
 			continue;
 
 		if (!compat)
-			compat = &sdata->vif.bss_conf.chandef;
+			compat = &link_conf->chandef;
 
 		compat = cfg80211_chandef_compatible(
-				&sdata->vif.bss_conf.chandef, compat);
+				&link_conf->chandef, compat);
 		if (!compat)
 			break;
 	}
@@ -157,7 +168,7 @@ ieee80211_chanctx_can_reserve_chandef(struct ieee80211_local *local,
 	if (ieee80211_chanctx_combined_chandef(local, ctx, def))
 		return true;
 
-	if (!list_empty(&ctx->reserved_vifs) &&
+	if (!list_empty(&ctx->reserved_links) &&
 	    ieee80211_chanctx_reserved_chandef(local, ctx, def))
 		return true;
 
@@ -193,13 +204,19 @@ ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
 	return NULL;
 }
 
-static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta)
+static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta,
+						    unsigned int link_id)
 {
-	enum ieee80211_sta_rx_bandwidth width = ieee80211_sta_cap_rx_bw(sta);
+	enum ieee80211_sta_rx_bandwidth width =
+		ieee80211_sta_cap_rx_bw(sta, link_id);
+
+	/* no effect if this STA has no presence on this link */
+	if (!sta->sta.link[link_id])
+		return NL80211_CHAN_WIDTH_20_NOHT;
 
 	switch (width) {
 	case IEEE80211_STA_RX_BW_20:
-		if (sta->sta.deflink.ht_cap.ht_supported)
+		if (sta->sta.link[link_id]->ht_cap.ht_supported)
 			return NL80211_CHAN_WIDTH_20;
 		else
 			return NL80211_CHAN_WIDTH_20_NOHT;
@@ -227,7 +244,8 @@ static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta)
 }
 
 static enum nl80211_chan_width
-ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
+ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata,
+			      unsigned int link_id)
 {
 	enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
 	struct sta_info *sta;
@@ -238,7 +256,7 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
 		    !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
 			continue;
 
-		max_bw = max(max_bw, ieee80211_get_sta_bw(sta));
+		max_bw = max(max_bw, ieee80211_get_sta_bw(sta, link_id));
 	}
 	rcu_read_unlock();
 
@@ -246,27 +264,28 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata)
 }
 
 static enum nl80211_chan_width
-ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
-				      struct ieee80211_chanctx_conf *conf)
+ieee80211_get_chanctx_vif_max_required_bw(struct ieee80211_sub_if_data *sdata,
+					  struct ieee80211_chanctx_conf *conf)
 {
-	struct ieee80211_sub_if_data *sdata;
 	enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
+	struct ieee80211_vif *vif = &sdata->vif;
+	int link_id;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		struct ieee80211_vif *vif = &sdata->vif;
+	for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
 		enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
+		struct ieee80211_bss_conf *link_conf =
+			sdata->vif.link_conf[link_id];
 
-		if (!ieee80211_sdata_running(sdata))
+		if (!link_conf)
 			continue;
 
-		if (rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) != conf)
+		if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
 			continue;
 
 		switch (vif->type) {
 		case NL80211_IFTYPE_AP:
 		case NL80211_IFTYPE_AP_VLAN:
-			width = ieee80211_get_max_required_bw(sdata);
+			width = ieee80211_get_max_required_bw(sdata, link_id);
 			break;
 		case NL80211_IFTYPE_STATION:
 			/*
@@ -274,8 +293,8 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
 			 * point, so take the width from the chandef, but
 			 * account also for TDLS peers
 			 */
-			width = max(vif->bss_conf.chandef.width,
-				    ieee80211_get_max_required_bw(sdata));
+			width = max(link_conf->chandef.width,
+				    ieee80211_get_max_required_bw(sdata, link_id));
 			break;
 		case NL80211_IFTYPE_P2P_DEVICE:
 		case NL80211_IFTYPE_NAN:
@@ -283,7 +302,7 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
 		case NL80211_IFTYPE_ADHOC:
 		case NL80211_IFTYPE_MESH_POINT:
 		case NL80211_IFTYPE_OCB:
-			width = vif->bss_conf.chandef.width;
+			width = link_conf->chandef.width;
 			break;
 		case NL80211_IFTYPE_WDS:
 		case NL80211_IFTYPE_UNSPECIFIED:
@@ -293,12 +312,36 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
 		case NL80211_IFTYPE_P2P_GO:
 			WARN_ON_ONCE(1);
 		}
+
+		max_bw = max(max_bw, width);
+	}
+
+	return max_bw;
+}
+
+static enum nl80211_chan_width
+ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
+				      struct ieee80211_chanctx_conf *conf)
+{
+	struct ieee80211_sub_if_data *sdata;
+	enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+		enum nl80211_chan_width width;
+
+		if (!ieee80211_sdata_running(sdata))
+			continue;
+
+		width = ieee80211_get_chanctx_vif_max_required_bw(sdata, conf);
+
 		max_bw = max(max_bw, width);
 	}
 
 	/* use the configured bandwidth in case of monitor interface */
 	sdata = rcu_dereference(local->monitor_sdata);
-	if (sdata && rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == conf)
+	if (sdata &&
+	    rcu_access_pointer(sdata->vif.link_conf[0]->chanctx_conf) == conf)
 		max_bw = max(max_bw, conf->def.width);
 
 	rcu_read_unlock();
@@ -350,7 +393,7 @@ static u32 _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
 }
 
 /* calling this function is assuming that station vif is updated to
- * lates changes by calling ieee80211_vif_update_chandef
+ * lates changes by calling ieee80211_link_update_chandef
  */
 static void ieee80211_chan_bw_change(struct ieee80211_local *local,
 				     struct ieee80211_chanctx *ctx,
@@ -363,29 +406,38 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local,
 	rcu_read_lock();
 	list_for_each_entry_rcu(sta, &local->sta_list,
 				list) {
+		struct ieee80211_sub_if_data *sdata = sta->sdata;
 		enum ieee80211_sta_rx_bandwidth new_sta_bw;
+		unsigned int link_id;
 
 		if (!ieee80211_sdata_running(sta->sdata))
 			continue;
 
-		if (rcu_access_pointer(sta->sdata->vif.bss_conf.chanctx_conf) !=
-		    &ctx->conf)
-			continue;
+		for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
+			struct ieee80211_bss_conf *link_conf =
+				sdata->vif.link_conf[link_id];
+
+			if (!link_conf)
+				continue;
 
-		new_sta_bw = ieee80211_sta_cur_vht_bw(sta);
+			if (rcu_access_pointer(link_conf->chanctx_conf) != &ctx->conf)
+				continue;
 
-		/* nothing change */
-		if (new_sta_bw == sta->sta.deflink.bandwidth)
-			continue;
+			new_sta_bw = ieee80211_sta_cur_vht_bw(sta, link_id);
 
-		/* vif changed to narrow BW and narrow BW for station wasn't
-		 * requested or vise versa */
-		if ((new_sta_bw < sta->sta.deflink.bandwidth) == !narrowed)
-			continue;
+			/* nothing change */
+			if (new_sta_bw == sta->sta.link[link_id]->bandwidth)
+				continue;
+
+			/* vif changed to narrow BW and narrow BW for station wasn't
+			 * requested or vise versa */
+			if ((new_sta_bw < sta->sta.link[link_id]->bandwidth) == !narrowed)
+				continue;
 
-		sta->sta.deflink.bandwidth = new_sta_bw;
-		rate_control_rate_update(local, sband, sta,
-					 IEEE80211_RC_BW_CHANGED);
+			sta->sta.link[link_id]->bandwidth = new_sta_bw;
+			rate_control_rate_update(local, sband, sta, link_id,
+						 IEEE80211_RC_BW_CHANGED);
+		}
 	}
 	rcu_read_unlock();
 }
@@ -508,9 +560,14 @@ bool ieee80211_is_radar_required(struct ieee80211_local *local)
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (sdata->deflink.radar_required) {
-			rcu_read_unlock();
-			return true;
+		unsigned int link_id;
+
+		for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
+			if (sdata->link[link_id] &&
+			    sdata->link[link_id]->radar_required) {
+				rcu_read_unlock();
+				return true;
+			}
 		}
 	}
 	rcu_read_unlock();
@@ -531,15 +588,27 @@ ieee80211_chanctx_radar_required(struct ieee80211_local *local,
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+		unsigned int link_id;
+
 		if (!ieee80211_sdata_running(sdata))
 			continue;
-		if (rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) != conf)
-			continue;
-		if (!sdata->deflink.radar_required)
-			continue;
+		for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
+			struct ieee80211_bss_conf *link_conf =
+				sdata->vif.link_conf[link_id];
 
-		required = true;
-		break;
+			if (!link_conf)
+				continue;
+
+			if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
+				continue;
+			if (!sdata->link[link_id]->radar_required)
+				continue;
+			required = true;
+			break;
+		}
+
+		if (required)
+			break;
 	}
 	rcu_read_unlock();
 
@@ -559,8 +628,8 @@ ieee80211_alloc_chanctx(struct ieee80211_local *local,
 	if (!ctx)
 		return NULL;
 
-	INIT_LIST_HEAD(&ctx->assigned_vifs);
-	INIT_LIST_HEAD(&ctx->reserved_vifs);
+	INIT_LIST_HEAD(&ctx->assigned_links);
+	INIT_LIST_HEAD(&ctx->reserved_links);
 	ctx->conf.def = *chandef;
 	ctx->conf.rx_chains_static = 1;
 	ctx->conf.rx_chains_dynamic = 1;
@@ -686,21 +755,32 @@ void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+		int link_id;
 
 		if (!ieee80211_sdata_running(sdata))
 			continue;
-		if (rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) != conf)
-			continue;
+
 		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 			continue;
 
-		if (!compat)
-			compat = &sdata->vif.bss_conf.chandef;
+		for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
+			struct ieee80211_bss_conf *link_conf =
+				sdata->vif.link_conf[link_id];
 
-		compat = cfg80211_chandef_compatible(
-				&sdata->vif.bss_conf.chandef, compat);
-		if (WARN_ON_ONCE(!compat))
-			break;
+			if (!link_conf)
+				continue;
+
+			if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
+				continue;
+
+			if (!compat)
+				compat = &link_conf->chandef;
+
+			compat = cfg80211_chandef_compatible(&link_conf->chandef,
+							     compat);
+			if (WARN_ON_ONCE(!compat))
+				break;
+		}
 	}
 
 	/* TDLS peers can sometimes affect the chandef width */
@@ -748,9 +828,11 @@ static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
 	drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
 }
 
-static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
-					struct ieee80211_chanctx *new_ctx)
+static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
+					 struct ieee80211_chanctx *new_ctx)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	unsigned int link_id = link->link_id;
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_chanctx_conf *conf;
 	struct ieee80211_chanctx *curr_ctx = NULL;
@@ -759,29 +841,29 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
 	if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
 		return -ENOTSUPP;
 
-	conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf,
+	conf = rcu_dereference_protected(sdata->vif.link_conf[link_id]->chanctx_conf,
 					 lockdep_is_held(&local->chanctx_mtx));
 
 	if (conf) {
 		curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
 
-		drv_unassign_vif_chanctx(local, sdata, curr_ctx);
+		drv_unassign_vif_chanctx(local, sdata, link_id, curr_ctx);
 		conf = NULL;
-		list_del(&sdata->assigned_chanctx_list);
+		list_del(&link->assigned_chanctx_list);
 	}
 
 	if (new_ctx) {
-		ret = drv_assign_vif_chanctx(local, sdata, new_ctx);
+		ret = drv_assign_vif_chanctx(local, sdata, link_id, new_ctx);
 		if (ret)
 			goto out;
 
 		conf = &new_ctx->conf;
-		list_add(&sdata->assigned_chanctx_list,
-			 &new_ctx->assigned_vifs);
+		list_add(&link->assigned_chanctx_list,
+			 &new_ctx->assigned_links);
 	}
 
 out:
-	rcu_assign_pointer(sdata->vif.bss_conf.chanctx_conf, conf);
+	rcu_assign_pointer(sdata->vif.link_conf[link_id]->chanctx_conf, conf);
 
 	sdata->vif.cfg.idle = !conf;
 
@@ -820,60 +902,64 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 		u8 needed_static, needed_dynamic;
+		unsigned int link_id;
 
 		if (!ieee80211_sdata_running(sdata))
 			continue;
 
-		if (rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) !=
-						&chanctx->conf)
-			continue;
-
 		switch (sdata->vif.type) {
-		case NL80211_IFTYPE_P2P_DEVICE:
-		case NL80211_IFTYPE_NAN:
-			continue;
 		case NL80211_IFTYPE_STATION:
 			if (!sdata->u.mgd.associated)
 				continue;
 			break;
-		case NL80211_IFTYPE_AP_VLAN:
-			continue;
 		case NL80211_IFTYPE_AP:
 		case NL80211_IFTYPE_ADHOC:
 		case NL80211_IFTYPE_MESH_POINT:
 		case NL80211_IFTYPE_OCB:
 			break;
 		default:
-			WARN_ON_ONCE(1);
+			continue;
 		}
 
-		switch (sdata->deflink.smps_mode) {
-		default:
-			WARN_ONCE(1, "Invalid SMPS mode %d\n",
-				  sdata->deflink.smps_mode);
-			fallthrough;
-		case IEEE80211_SMPS_OFF:
-			needed_static = sdata->deflink.needed_rx_chains;
-			needed_dynamic = sdata->deflink.needed_rx_chains;
-			break;
-		case IEEE80211_SMPS_DYNAMIC:
-			needed_static = 1;
-			needed_dynamic = sdata->deflink.needed_rx_chains;
-			break;
-		case IEEE80211_SMPS_STATIC:
-			needed_static = 1;
-			needed_dynamic = 1;
-			break;
-		}
+		for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
+			struct ieee80211_link_data *link = sdata->link[link_id];
+			struct ieee80211_bss_conf *link_conf =
+				sdata->vif.link_conf[link_id];
+
+			if (!link_conf)
+				continue;
+
+			if (rcu_access_pointer(link_conf->chanctx_conf) != &chanctx->conf)
+				continue;
+
+			switch (link->smps_mode) {
+			default:
+				WARN_ONCE(1, "Invalid SMPS mode %d\n",
+					  link->smps_mode);
+				fallthrough;
+			case IEEE80211_SMPS_OFF:
+				needed_static = link->needed_rx_chains;
+				needed_dynamic = link->needed_rx_chains;
+				break;
+			case IEEE80211_SMPS_DYNAMIC:
+				needed_static = 1;
+				needed_dynamic = link->needed_rx_chains;
+				break;
+			case IEEE80211_SMPS_STATIC:
+				needed_static = 1;
+				needed_dynamic = 1;
+				break;
+			}
 
-		rx_chains_static = max(rx_chains_static, needed_static);
-		rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
+			rx_chains_static = max(rx_chains_static, needed_static);
+			rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
+		}
 	}
 
 	/* Disable SMPS for the monitor interface */
 	sdata = rcu_dereference(local->monitor_sdata);
 	if (sdata &&
-	    rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &chanctx->conf)
+	    rcu_access_pointer(sdata->vif.link_conf[0]->chanctx_conf) == &chanctx->conf)
 		rx_chains_dynamic = rx_chains_static = local->rx_chains;
 
 	rcu_read_unlock();
@@ -898,9 +984,12 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
 }
 
 static void
-__ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
-				      bool clear)
+__ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
+				       bool clear)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	unsigned int link_id = link->link_id;
+	struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
 	struct ieee80211_local *local __maybe_unused = sdata->local;
 	struct ieee80211_sub_if_data *vlan;
 	struct ieee80211_chanctx_conf *conf;
@@ -916,7 +1005,7 @@ __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
 	 * channel context pointer for a while, possibly pointing
 	 * to a channel context that has already been freed.
 	 */
-	conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf,
+	conf = rcu_dereference_protected(link_conf->chanctx_conf,
 					 lockdep_is_held(&local->chanctx_mtx));
 	WARN_ON(!conf);
 
@@ -924,32 +1013,34 @@ __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
 		conf = NULL;
 
 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
-		rcu_assign_pointer(vlan->vif.bss_conf.chanctx_conf, conf);
+		rcu_assign_pointer(vlan->vif.link_conf[link_id]->chanctx_conf,
+				   conf);
 }
 
-void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
-					 bool clear)
+void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
+					  bool clear)
 {
-	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_local *local = link->sdata->local;
 
 	mutex_lock(&local->chanctx_mtx);
 
-	__ieee80211_vif_copy_chanctx_to_vlans(sdata, clear);
+	__ieee80211_link_copy_chanctx_to_vlans(link, clear);
 
 	mutex_unlock(&local->chanctx_mtx);
 }
 
-int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata)
+int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)
 {
-	struct ieee80211_chanctx *ctx = sdata->deflink.reserved_chanctx;
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	struct ieee80211_chanctx *ctx = link->reserved_chanctx;
 
 	lockdep_assert_held(&sdata->local->chanctx_mtx);
 
 	if (WARN_ON(!ctx))
 		return -EINVAL;
 
-	list_del(&sdata->reserved_chanctx_list);
-	sdata->deflink.reserved_chanctx = NULL;
+	list_del(&link->reserved_chanctx_list);
+	link->reserved_chanctx = NULL;
 
 	if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) {
 		if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
@@ -974,17 +1065,18 @@ int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata)
 	return 0;
 }
 
-int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
-				  const struct cfg80211_chan_def *chandef,
-				  enum ieee80211_chanctx_mode mode,
-				  bool radar_required)
+int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
+				   const struct cfg80211_chan_def *chandef,
+				   enum ieee80211_chanctx_mode mode,
+				   bool radar_required)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_chanctx *new_ctx, *curr_ctx, *ctx;
 
 	lockdep_assert_held(&local->chanctx_mtx);
 
-	curr_ctx = ieee80211_vif_get_chanctx(sdata);
+	curr_ctx = ieee80211_link_get_chanctx(link);
 	if (curr_ctx && local->use_chanctx && !local->ops->switch_vif_chanctx)
 		return -ENOTSUPP;
 
@@ -998,11 +1090,11 @@ int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
 			if (!curr_ctx ||
 			    (curr_ctx->replace_state ==
 			     IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
-			    !list_empty(&curr_ctx->reserved_vifs)) {
+			    !list_empty(&curr_ctx->reserved_links)) {
 				/*
-				 * Another vif already requested this context
+				 * Another link already requested this context
 				 * for a reservation. Find another one hoping
-				 * all vifs assigned to it will also switch
+				 * all links assigned to it will also switch
 				 * soon enough.
 				 *
 				 * TODO: This needs a little more work as some
@@ -1011,13 +1103,13 @@ int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
 				 * provided some channel context juggling was
 				 * performed.
 				 *
-				 * Consider ctx1..3, vif1..6, each ctx has 2
-				 * vifs. vif1 and vif2 from ctx1 request new
+				 * Consider ctx1..3, link1..6, each ctx has 2
+				 * links. link1 and link2 from ctx1 request new
 				 * different chandefs starting 2 in-place
 				 * reserations with ctx4 and ctx5 replacing
-				 * ctx1 and ctx2 respectively. Next vif5 and
-				 * vif6 from ctx3 reserve ctx4. If vif3 and
-				 * vif4 remain on ctx2 as they are then this
+				 * ctx1 and ctx2 respectively. Next link5 and
+				 * link6 from ctx3 reserve ctx4. If link3 and
+				 * link4 remain on ctx2 as they are then this
 				 * fails unless `replace_ctx` from ctx5 is
 				 * replaced with ctx3.
 				 */
@@ -1027,7 +1119,7 @@ int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
 					    IEEE80211_CHANCTX_REPLACE_NONE)
 						continue;
 
-					if (!list_empty(&ctx->reserved_vifs))
+					if (!list_empty(&ctx->reserved_links))
 						continue;
 
 					curr_ctx = ctx;
@@ -1042,7 +1134,7 @@ int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
 			if (!curr_ctx ||
 			    (curr_ctx->replace_state ==
 			     IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
-			    !list_empty(&curr_ctx->reserved_vifs))
+			    !list_empty(&curr_ctx->reserved_links))
 				return -EBUSY;
 
 			new_ctx = ieee80211_alloc_chanctx(local, chandef, mode);
@@ -1061,25 +1153,27 @@ int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
 		}
 	}
 
-	list_add(&sdata->reserved_chanctx_list, &new_ctx->reserved_vifs);
-	sdata->deflink.reserved_chanctx = new_ctx;
-	sdata->deflink.reserved_chandef = *chandef;
-	sdata->deflink.reserved_radar_required = radar_required;
-	sdata->deflink.reserved_ready = false;
+	list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links);
+	link->reserved_chanctx = new_ctx;
+	link->reserved_chandef = *chandef;
+	link->reserved_radar_required = radar_required;
+	link->reserved_ready = false;
 
 	return 0;
 }
 
 static void
-ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data *sdata)
+ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_ADHOC:
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_MESH_POINT:
 	case NL80211_IFTYPE_OCB:
 		ieee80211_queue_work(&sdata->local->hw,
-				     &sdata->deflink.csa_finalize_work);
+				     &link->csa_finalize_work);
 		break;
 	case NL80211_IFTYPE_STATION:
 		ieee80211_queue_work(&sdata->local->hw,
@@ -1100,23 +1194,28 @@ ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data *sdata)
 }
 
 static void
-ieee80211_vif_update_chandef(struct ieee80211_sub_if_data *sdata,
-			     const struct cfg80211_chan_def *chandef)
+ieee80211_link_update_chandef(struct ieee80211_link_data *link,
+			      const struct cfg80211_chan_def *chandef)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	unsigned int link_id = link->link_id;
 	struct ieee80211_sub_if_data *vlan;
 
-	sdata->vif.bss_conf.chandef = *chandef;
+	sdata->vif.link_conf[link_id]->chandef = *chandef;
 
 	if (sdata->vif.type != NL80211_IFTYPE_AP)
 		return;
 
 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
-		vlan->vif.bss_conf.chandef = *chandef;
+		vlan->vif.link_conf[link_id]->chandef = *chandef;
 }
 
 static int
-ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
+ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	unsigned int link_id = link->link_id;
+	struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_vif_chanctx_switch vif_chsw[1] = {};
 	struct ieee80211_chanctx *old_ctx, *new_ctx;
@@ -1127,10 +1226,10 @@ ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
 	lockdep_assert_held(&local->mtx);
 	lockdep_assert_held(&local->chanctx_mtx);
 
-	new_ctx = sdata->deflink.reserved_chanctx;
-	old_ctx = ieee80211_vif_get_chanctx(sdata);
+	new_ctx = link->reserved_chanctx;
+	old_ctx = ieee80211_link_get_chanctx(link);
 
-	if (WARN_ON(!sdata->deflink.reserved_ready))
+	if (WARN_ON(!link->reserved_ready))
 		return -EBUSY;
 
 	if (WARN_ON(!new_ctx))
@@ -1144,23 +1243,24 @@ ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
 		return -EINVAL;
 
 	chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
-				&sdata->deflink.reserved_chandef);
+				&link->reserved_chandef);
 	if (WARN_ON(!chandef))
 		return -EINVAL;
 
-	if (sdata->vif.bss_conf.chandef.width != sdata->deflink.reserved_chandef.width)
+	if (link_conf->chandef.width != link->reserved_chandef.width)
 		changed = BSS_CHANGED_BANDWIDTH;
 
-	ieee80211_vif_update_chandef(sdata, &sdata->deflink.reserved_chandef);
+	ieee80211_link_update_chandef(link, &link->reserved_chandef);
 
 	ieee80211_change_chanctx(local, new_ctx, old_ctx, chandef);
 
 	vif_chsw[0].vif = &sdata->vif;
 	vif_chsw[0].old_ctx = &old_ctx->conf;
 	vif_chsw[0].new_ctx = &new_ctx->conf;
+	vif_chsw[0].link_id = link->link_id;
 
-	list_del(&sdata->reserved_chanctx_list);
-	sdata->deflink.reserved_chanctx = NULL;
+	list_del(&link->reserved_chanctx_list);
+	link->reserved_chanctx = NULL;
 
 	err = drv_switch_vif_chanctx(local, vif_chsw, 1,
 				     CHANCTX_SWMODE_REASSIGN_VIF);
@@ -1171,11 +1271,11 @@ ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
 		goto out;
 	}
 
-	list_move(&sdata->assigned_chanctx_list, &new_ctx->assigned_vifs);
-	rcu_assign_pointer(sdata->vif.bss_conf.chanctx_conf, &new_ctx->conf);
+	list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links);
+	rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf);
 
 	if (sdata->vif.type == NL80211_IFTYPE_AP)
-		__ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
+		__ieee80211_link_copy_chanctx_to_vlans(link, false);
 
 	ieee80211_check_fast_xmit_iface(sdata);
 
@@ -1187,25 +1287,27 @@ ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
 	ieee80211_recalc_radar_chanctx(local, new_ctx);
 
 	if (changed)
-		ieee80211_link_info_change_notify(sdata, 0, changed);
+		ieee80211_link_info_change_notify(sdata, link_id, changed);
 
 out:
-	ieee80211_vif_chanctx_reservation_complete(sdata);
+	ieee80211_link_chanctx_reservation_complete(link);
 	return err;
 }
 
 static int
-ieee80211_vif_use_reserved_assign(struct ieee80211_sub_if_data *sdata)
+ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	unsigned int link_id = link->link_id;
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_chanctx *old_ctx, *new_ctx;
 	const struct cfg80211_chan_def *chandef;
 	int err;
 
-	old_ctx = ieee80211_vif_get_chanctx(sdata);
-	new_ctx = sdata->deflink.reserved_chanctx;
+	old_ctx = ieee80211_vif_get_chanctx(sdata, link_id);
+	new_ctx = link->reserved_chanctx;
 
-	if (WARN_ON(!sdata->deflink.reserved_ready))
+	if (WARN_ON(!link->reserved_ready))
 		return -EINVAL;
 
 	if (WARN_ON(old_ctx))
@@ -1219,16 +1321,16 @@ ieee80211_vif_use_reserved_assign(struct ieee80211_sub_if_data *sdata)
 		return -EINVAL;
 
 	chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
-				&sdata->deflink.reserved_chandef);
+				&link->reserved_chandef);
 	if (WARN_ON(!chandef))
 		return -EINVAL;
 
 	ieee80211_change_chanctx(local, new_ctx, new_ctx, chandef);
 
-	list_del(&sdata->reserved_chanctx_list);
-	sdata->deflink.reserved_chanctx = NULL;
+	list_del(&link->reserved_chanctx_list);
+	link->reserved_chanctx = NULL;
 
-	err = ieee80211_assign_vif_chanctx(sdata, new_ctx);
+	err = ieee80211_assign_link_chanctx(link, new_ctx);
 	if (err) {
 		if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
 			ieee80211_free_chanctx(local, new_ctx);
@@ -1237,19 +1339,20 @@ ieee80211_vif_use_reserved_assign(struct ieee80211_sub_if_data *sdata)
 	}
 
 out:
-	ieee80211_vif_chanctx_reservation_complete(sdata);
+	ieee80211_link_chanctx_reservation_complete(link);
 	return err;
 }
 
 static bool
-ieee80211_vif_has_in_place_reservation(struct ieee80211_sub_if_data *sdata)
+ieee80211_link_has_in_place_reservation(struct ieee80211_link_data *link)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
 	struct ieee80211_chanctx *old_ctx, *new_ctx;
 
 	lockdep_assert_held(&sdata->local->chanctx_mtx);
 
-	new_ctx = sdata->deflink.reserved_chanctx;
-	old_ctx = ieee80211_vif_get_chanctx(sdata);
+	new_ctx = link->reserved_chanctx;
+	old_ctx = ieee80211_link_get_chanctx(link);
 
 	if (!old_ctx)
 		return false;
@@ -1289,7 +1392,7 @@ static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
 				      int n_vifs)
 {
 	struct ieee80211_vif_chanctx_switch *vif_chsw;
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_link_data *link;
 	struct ieee80211_chanctx *ctx, *old_ctx;
 	int i, err;
 
@@ -1310,16 +1413,16 @@ static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
 			goto out;
 		}
 
-		list_for_each_entry(sdata, &ctx->reserved_vifs,
+		list_for_each_entry(link, &ctx->reserved_links,
 				    reserved_chanctx_list) {
-			if (!ieee80211_vif_has_in_place_reservation(
-					sdata))
+			if (!ieee80211_link_has_in_place_reservation(link))
 				continue;
 
-			old_ctx = ieee80211_vif_get_chanctx(sdata);
-			vif_chsw[i].vif = &sdata->vif;
+			old_ctx = ieee80211_link_get_chanctx(link);
+			vif_chsw[i].vif = &link->sdata->vif;
 			vif_chsw[i].old_ctx = &old_ctx->conf;
 			vif_chsw[i].new_ctx = &ctx->conf;
+			vif_chsw[i].link_id = link->link_id;
 
 			i++;
 		}
@@ -1345,7 +1448,7 @@ static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
 			continue;
 
-		if (!list_empty(&ctx->replace_ctx->assigned_vifs))
+		if (!list_empty(&ctx->replace_ctx->assigned_links))
 			continue;
 
 		ieee80211_del_chanctx(local, ctx->replace_ctx);
@@ -1362,7 +1465,7 @@ static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
 			continue;
 
-		if (!list_empty(&ctx->replace_ctx->assigned_vifs))
+		if (!list_empty(&ctx->replace_ctx->assigned_links))
 			continue;
 
 		ieee80211_del_chanctx(local, ctx);
@@ -1374,7 +1477,6 @@ static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
 
 static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 {
-	struct ieee80211_sub_if_data *sdata, *sdata_tmp;
 	struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
 	struct ieee80211_chanctx *new_ctx = NULL;
 	int err, n_assigned, n_reserved, n_ready;
@@ -1400,6 +1502,8 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 	 */
 
 	list_for_each_entry(ctx, &local->chanctx_list, list) {
+		struct ieee80211_link_data *link;
+
 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
 			continue;
 
@@ -1417,12 +1521,12 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 		n_reserved = 0;
 		n_ready = 0;
 
-		list_for_each_entry(sdata, &ctx->replace_ctx->assigned_vifs,
+		list_for_each_entry(link, &ctx->replace_ctx->assigned_links,
 				    assigned_chanctx_list) {
 			n_assigned++;
-			if (sdata->deflink.reserved_chanctx) {
+			if (link->reserved_chanctx) {
 				n_reserved++;
-				if (sdata->deflink.reserved_ready)
+				if (link->reserved_ready)
 					n_ready++;
 			}
 		}
@@ -1439,13 +1543,13 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 		}
 
 		ctx->conf.radar_enabled = false;
-		list_for_each_entry(sdata, &ctx->reserved_vifs,
+		list_for_each_entry(link, &ctx->reserved_links,
 				    reserved_chanctx_list) {
-			if (ieee80211_vif_has_in_place_reservation(sdata) &&
-			    !sdata->deflink.reserved_ready)
+			if (ieee80211_link_has_in_place_reservation(link) &&
+			    !link->reserved_ready)
 				return -EAGAIN;
 
-			old_ctx = ieee80211_vif_get_chanctx(sdata);
+			old_ctx = ieee80211_link_get_chanctx(link);
 			if (old_ctx) {
 				if (old_ctx->replace_state ==
 				    IEEE80211_CHANCTX_WILL_BE_REPLACED)
@@ -1456,7 +1560,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 				n_vifs_ctxless++;
 			}
 
-			if (sdata->deflink.reserved_radar_required)
+			if (link->reserved_radar_required)
 				ctx->conf.radar_enabled = true;
 		}
 	}
@@ -1499,6 +1603,8 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 	 * context(s).
 	 */
 	list_for_each_entry(ctx, &local->chanctx_list, list) {
+		struct ieee80211_link_data *link, *link_tmp;
+
 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
 			continue;
 
@@ -1507,32 +1613,34 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 			goto err;
 		}
 
-		list_for_each_entry(sdata, &ctx->reserved_vifs,
+		list_for_each_entry(link, &ctx->reserved_links,
 				    reserved_chanctx_list) {
+			struct ieee80211_sub_if_data *sdata = link->sdata;
+			struct ieee80211_bss_conf *link_conf =
+				sdata->vif.link_conf[link->link_id];
 			u32 changed = 0;
 
-			if (!ieee80211_vif_has_in_place_reservation(sdata))
+			if (!ieee80211_link_has_in_place_reservation(link))
 				continue;
 
-			rcu_assign_pointer(sdata->vif.bss_conf.chanctx_conf,
+			rcu_assign_pointer(link_conf->chanctx_conf,
 					   &ctx->conf);
 
 			if (sdata->vif.type == NL80211_IFTYPE_AP)
-				__ieee80211_vif_copy_chanctx_to_vlans(sdata,
-								      false);
+				__ieee80211_link_copy_chanctx_to_vlans(link,
+								       false);
 
 			ieee80211_check_fast_xmit_iface(sdata);
 
-			sdata->deflink.radar_required = sdata->deflink.reserved_radar_required;
+			link->radar_required = link->reserved_radar_required;
 
-			if (sdata->vif.bss_conf.chandef.width !=
-			    sdata->deflink.reserved_chandef.width)
+			if (link_conf->chandef.width != link->reserved_chandef.width)
 				changed = BSS_CHANGED_BANDWIDTH;
 
-			ieee80211_vif_update_chandef(sdata,
-						     &sdata->deflink.reserved_chandef);
+			ieee80211_link_update_chandef(link, &link->reserved_chandef);
 			if (changed)
-				ieee80211_link_info_change_notify(sdata, 0,
+				ieee80211_link_info_change_notify(sdata,
+								  link->link_id,
 								  changed);
 
 			ieee80211_recalc_txpower(sdata, false);
@@ -1543,17 +1651,17 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 		ieee80211_recalc_radar_chanctx(local, ctx);
 		ieee80211_recalc_chanctx_min_def(local, ctx);
 
-		list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
+		list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
 					 reserved_chanctx_list) {
-			if (ieee80211_vif_get_chanctx(sdata) != ctx)
+			if (ieee80211_link_get_chanctx(link) != ctx)
 				continue;
 
-			list_del(&sdata->reserved_chanctx_list);
-			list_move(&sdata->assigned_chanctx_list,
-				  &ctx->assigned_vifs);
-			sdata->deflink.reserved_chanctx = NULL;
+			list_del(&link->reserved_chanctx_list);
+			list_move(&link->assigned_chanctx_list,
+				  &ctx->assigned_links);
+			link->reserved_chanctx = NULL;
 
-			ieee80211_vif_chanctx_reservation_complete(sdata);
+			ieee80211_link_chanctx_reservation_complete(link);
 		}
 
 		/*
@@ -1563,31 +1671,29 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 		 * reservation for originally requested interface has already
 		 * succeeded at this point.
 		 */
-		list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
+		list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
 					 reserved_chanctx_list) {
-			if (WARN_ON(ieee80211_vif_has_in_place_reservation(
-					sdata)))
+			if (WARN_ON(ieee80211_link_has_in_place_reservation(link)))
 				continue;
 
-			if (WARN_ON(sdata->deflink.reserved_chanctx != ctx))
+			if (WARN_ON(link->reserved_chanctx != ctx))
 				continue;
 
-			if (!sdata->deflink.reserved_ready)
+			if (!link->reserved_ready)
 				continue;
 
-			if (ieee80211_vif_get_chanctx(sdata))
-				err = ieee80211_vif_use_reserved_reassign(
-						sdata);
+			if (ieee80211_link_get_chanctx(link))
+				err = ieee80211_link_use_reserved_reassign(link);
 			else
-				err = ieee80211_vif_use_reserved_assign(sdata);
+				err = ieee80211_link_use_reserved_assign(link);
 
 			if (err) {
-				sdata_info(sdata,
-					   "failed to finalize (re-)assign reservation (err=%d)\n",
-					   err);
-				ieee80211_vif_unreserve_chanctx(sdata);
+				link_info(link,
+					  "failed to finalize (re-)assign reservation (err=%d)\n",
+					  err);
+				ieee80211_link_unreserve_chanctx(link);
 				cfg80211_stop_iface(local->hw.wiphy,
-						    &sdata->wdev,
+						    &link->sdata->wdev,
 						    GFP_KERNEL);
 			}
 		}
@@ -1613,21 +1719,26 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 
 err:
 	list_for_each_entry(ctx, &local->chanctx_list, list) {
+		struct ieee80211_link_data *link, *link_tmp;
+
 		if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
 			continue;
 
-		list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs,
+		list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
 					 reserved_chanctx_list) {
-			ieee80211_vif_unreserve_chanctx(sdata);
-			ieee80211_vif_chanctx_reservation_complete(sdata);
+			ieee80211_link_unreserve_chanctx(link);
+			ieee80211_link_chanctx_reservation_complete(link);
 		}
 	}
 
 	return err;
 }
 
-static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
+static void __ieee80211_link_release_channel(struct ieee80211_link_data *link)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	unsigned int link_id = link->link_id;
+	struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_chanctx_conf *conf;
 	struct ieee80211_chanctx *ctx;
@@ -1635,38 +1746,38 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
 
 	lockdep_assert_held(&local->chanctx_mtx);
 
-	conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf,
+	conf = rcu_dereference_protected(link_conf->chanctx_conf,
 					 lockdep_is_held(&local->chanctx_mtx));
 	if (!conf)
 		return;
 
 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
 
-	if (sdata->deflink.reserved_chanctx) {
-		if (sdata->deflink.reserved_chanctx->replace_state ==
-		    IEEE80211_CHANCTX_REPLACES_OTHER &&
-		    ieee80211_chanctx_num_reserved(local,
-						   sdata->deflink.reserved_chanctx) > 1)
+	if (link->reserved_chanctx) {
+		if (link->reserved_chanctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
+		    ieee80211_chanctx_num_reserved(local, link->reserved_chanctx) > 1)
 			use_reserved_switch = true;
 
-		ieee80211_vif_unreserve_chanctx(sdata);
+		ieee80211_link_unreserve_chanctx(link);
 	}
 
-	ieee80211_assign_vif_chanctx(sdata, NULL);
+	ieee80211_assign_link_chanctx(link, NULL);
 	if (ieee80211_chanctx_refcount(local, ctx) == 0)
 		ieee80211_free_chanctx(local, ctx);
 
-	sdata->deflink.radar_required = false;
+	link->radar_required = false;
 
 	/* Unreserving may ready an in-place reservation. */
 	if (use_reserved_switch)
 		ieee80211_vif_use_reserved_switch(local);
 }
 
-int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
-			      const struct cfg80211_chan_def *chandef,
-			      enum ieee80211_chanctx_mode mode)
+int ieee80211_link_use_channel(struct ieee80211_link_data *link,
+			       const struct cfg80211_chan_def *chandef,
+			       enum ieee80211_chanctx_mode mode)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	unsigned int link_id = link->link_id;
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_chanctx *ctx;
 	u8 radar_detect_width = 0;
@@ -1686,14 +1797,14 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
 	if (ret > 0)
 		radar_detect_width = BIT(chandef->width);
 
-	sdata->deflink.radar_required = ret;
+	sdata->link[link_id]->radar_required = ret;
 
 	ret = ieee80211_check_combinations(sdata, chandef, mode,
 					   radar_detect_width);
 	if (ret < 0)
 		goto out;
 
-	__ieee80211_vif_release_channel(sdata);
+	__ieee80211_link_release_channel(link);
 
 	ctx = ieee80211_find_chanctx(local, chandef, mode);
 	if (!ctx)
@@ -1703,9 +1814,9 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
 		goto out;
 	}
 
-	ieee80211_vif_update_chandef(sdata, chandef);
+	ieee80211_link_update_chandef(link, chandef);
 
-	ret = ieee80211_assign_vif_chanctx(sdata, ctx);
+	ret = ieee80211_assign_link_chanctx(link, ctx);
 	if (ret) {
 		/* if assign fails refcount stays the same */
 		if (ieee80211_chanctx_refcount(local, ctx) == 0)
@@ -1717,14 +1828,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
 	ieee80211_recalc_radar_chanctx(local, ctx);
  out:
 	if (ret)
-		sdata->deflink.radar_required = false;
+		link->radar_required = false;
 
 	mutex_unlock(&local->chanctx_mtx);
 	return ret;
 }
 
-int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata)
+int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_chanctx *new_ctx;
 	struct ieee80211_chanctx *old_ctx;
@@ -1733,8 +1845,8 @@ int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata)
 	lockdep_assert_held(&local->mtx);
 	lockdep_assert_held(&local->chanctx_mtx);
 
-	new_ctx = sdata->deflink.reserved_chanctx;
-	old_ctx = ieee80211_vif_get_chanctx(sdata);
+	new_ctx = link->reserved_chanctx;
+	old_ctx = ieee80211_link_get_chanctx(link);
 
 	if (WARN_ON(!new_ctx))
 		return -EINVAL;
@@ -1743,16 +1855,16 @@ int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata)
 		    IEEE80211_CHANCTX_WILL_BE_REPLACED))
 		return -EINVAL;
 
-	if (WARN_ON(sdata->deflink.reserved_ready))
+	if (WARN_ON(link->reserved_ready))
 		return -EINVAL;
 
-	sdata->deflink.reserved_ready = true;
+	link->reserved_ready = true;
 
 	if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) {
 		if (old_ctx)
-			return ieee80211_vif_use_reserved_reassign(sdata);
+			return ieee80211_link_use_reserved_reassign(link);
 
-		return ieee80211_vif_use_reserved_assign(sdata);
+		return ieee80211_link_use_reserved_assign(link);
 	}
 
 	/*
@@ -1784,10 +1896,13 @@ int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata)
 	return 0;
 }
 
-int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
-				   const struct cfg80211_chan_def *chandef,
-				   u32 *changed)
+int ieee80211_link_change_bandwidth(struct ieee80211_link_data *link,
+				    const struct cfg80211_chan_def *chandef,
+				    u32 *changed)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	unsigned int link_id = link->link_id;
+	struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_chanctx_conf *conf;
 	struct ieee80211_chanctx *ctx;
@@ -1799,18 +1914,18 @@ int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
 		return -EINVAL;
 
 	mutex_lock(&local->chanctx_mtx);
-	if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) {
+	if (cfg80211_chandef_identical(chandef, &link_conf->chandef)) {
 		ret = 0;
 		goto out;
 	}
 
 	if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
-	    sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
+	    link_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf,
+	conf = rcu_dereference_protected(link_conf->chanctx_conf,
 					 lockdep_is_held(&local->chanctx_mtx));
 	if (!conf) {
 		ret = -EINVAL;
@@ -1845,7 +1960,7 @@ int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
 		break;
 	}
 
-	ieee80211_vif_update_chandef(sdata, chandef);
+	ieee80211_link_update_chandef(link, chandef);
 
 	ieee80211_recalc_chanctx_chantype(local, ctx);
 
@@ -1856,19 +1971,24 @@ int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
 	return ret;
 }
 
-void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
+void ieee80211_link_release_channel(struct ieee80211_link_data *link)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+
 	WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
 
 	lockdep_assert_held(&sdata->local->mtx);
 
 	mutex_lock(&sdata->local->chanctx_mtx);
-	__ieee80211_vif_release_channel(sdata);
+	__ieee80211_link_release_channel(link);
 	mutex_unlock(&sdata->local->chanctx_mtx);
 }
 
-void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
+void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link)
 {
+	struct ieee80211_sub_if_data *sdata = link->sdata;
+	unsigned int link_id = link->link_id;
+	struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_sub_if_data *ap;
 	struct ieee80211_chanctx_conf *conf;
@@ -1880,9 +2000,9 @@ void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
 
 	mutex_lock(&local->chanctx_mtx);
 
-	conf = rcu_dereference_protected(ap->vif.bss_conf.chanctx_conf,
+	conf = rcu_dereference_protected(ap->vif.link_conf[link_id]->chanctx_conf,
 					 lockdep_is_held(&local->chanctx_mtx));
-	rcu_assign_pointer(sdata->vif.bss_conf.chanctx_conf, conf);
+	rcu_assign_pointer(link_conf->chanctx_conf, conf);
 	mutex_unlock(&local->chanctx_mtx);
 }
 
diff --git a/net/mac80211/debug.h b/net/mac80211/debug.h
index d90a8f9cc3fd..3302e8da0314 100644
--- a/net/mac80211/debug.h
+++ b/net/mac80211/debug.h
@@ -1,4 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Portions
+ * Copyright (C) 2022 Intel Corporation
+ */
 #ifndef __MAC80211_DEBUG_H
 #define __MAC80211_DEBUG_H
 #include <net/cfg80211.h>
@@ -130,6 +134,16 @@ do {									\
 #define sdata_dbg(sdata, fmt, ...)					\
 	_sdata_dbg(1, sdata, fmt, ##__VA_ARGS__)
 
+#define link_info(link, fmt, ...)					\
+	_sdata_info((link)->sdata, "[link %d] " fmt, (link)->link_id,	\
+		    ##__VA_ARGS__)
+#define link_err(link, fmt, ...)					\
+	_sdata_err((link)->sdata, "[link %d] " fmt, (link)->link_id,	\
+		   ##__VA_ARGS__)
+#define link_dbg(link, fmt, ...)					\
+	_sdata_dbg(1, (link)->sdata, "[link %d] " fmt, (link)->link_id,	\
+		   ##__VA_ARGS__)
+
 #define ht_dbg(sdata, fmt, ...)						\
 	_sdata_dbg(MAC80211_HT_DEBUG,					\
 		   sdata, fmt, ##__VA_ARGS__)
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 15ab8d00815b..9238283a8237 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -938,6 +938,7 @@ static inline void drv_change_chanctx(struct ieee80211_local *local,
 
 static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
 					 struct ieee80211_sub_if_data *sdata,
+					 unsigned int link_id,
 					 struct ieee80211_chanctx *ctx)
 {
 	int ret = 0;
@@ -945,11 +946,12 @@ static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
 	if (!check_sdata_in_driver(sdata))
 		return -EIO;
 
-	trace_drv_assign_vif_chanctx(local, sdata, ctx);
+	trace_drv_assign_vif_chanctx(local, sdata, link_id, ctx);
 	if (local->ops->assign_vif_chanctx) {
 		WARN_ON_ONCE(!ctx->driver_present);
 		ret = local->ops->assign_vif_chanctx(&local->hw,
 						     &sdata->vif,
+						     link_id,
 						     &ctx->conf);
 	}
 	trace_drv_return_int(local, ret);
@@ -959,6 +961,7 @@ static inline int drv_assign_vif_chanctx(struct ieee80211_local *local,
 
 static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
 					    struct ieee80211_sub_if_data *sdata,
+					    unsigned int link_id,
 					    struct ieee80211_chanctx *ctx)
 {
 	might_sleep();
@@ -966,11 +969,12 @@ static inline void drv_unassign_vif_chanctx(struct ieee80211_local *local,
 	if (!check_sdata_in_driver(sdata))
 		return;
 
-	trace_drv_unassign_vif_chanctx(local, sdata, ctx);
+	trace_drv_unassign_vif_chanctx(local, sdata, link_id, ctx);
 	if (local->ops->unassign_vif_chanctx) {
 		WARN_ON_ONCE(!ctx->driver_present);
 		local->ops->unassign_vif_chanctx(&local->hw,
 						 &sdata->vif,
+						 link_id,
 						 &ctx->conf);
 	}
 	trace_drv_return_void(local);
diff --git a/net/mac80211/eht.c b/net/mac80211/eht.c
index 96c9486bf2fe..2d9c6e845ce4 100644
--- a/net/mac80211/eht.c
+++ b/net/mac80211/eht.c
@@ -71,6 +71,6 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
 
 	eht_cap->has_eht = true;
 
-	sta->deflink.cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta);
-	sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta);
+	sta->deflink.cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta, 0);
+	sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta, 0);
 }
diff --git a/net/mac80211/he.c b/net/mac80211/he.c
index 1a61f7552edd..20448dda8c4d 100644
--- a/net/mac80211/he.c
+++ b/net/mac80211/he.c
@@ -3,7 +3,7 @@
  * HE handling
  *
  * Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2019 - 2020 Intel Corporation
+ * Copyright(c) 2019 - 2022 Intel Corporation
  */
 
 #include "ieee80211_i.h"
@@ -153,8 +153,8 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
 
 	he_cap->has_he = true;
 
-	sta->deflink.cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta);
-	sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta);
+	sta->deflink.cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta, 0);
+	sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta, 0);
 
 	if (sband->band == NL80211_BAND_6GHZ && he_6ghz_capa)
 		ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, sta);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 3b68e9f4345b..2ca75f2d3023 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -301,8 +301,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 	radar_required = err;
 
 	mutex_lock(&local->mtx);
-	if (ieee80211_vif_use_channel(sdata, &chandef,
-				      ifibss->fixed_channel ?
+	if (ieee80211_link_use_channel(sdata->link[0], &chandef,
+				       ifibss->fixed_channel ?
 					IEEE80211_CHANCTX_SHARED :
 					IEEE80211_CHANCTX_EXCLUSIVE)) {
 		sdata_info(sdata, "Failed to join IBSS, no channel context\n");
@@ -371,7 +371,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
 		RCU_INIT_POINTER(ifibss->presp, NULL);
 		kfree_rcu(presp, rcu_head);
 		mutex_lock(&local->mtx);
-		ieee80211_vif_release_channel(sdata);
+		ieee80211_link_release_channel(sdata->link[0]);
 		mutex_unlock(&local->mtx);
 		sdata_info(sdata, "Failed to join IBSS, driver failure: %d\n",
 			   err);
@@ -725,7 +725,7 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)
 						BSS_CHANGED_IBSS);
 	drv_leave_ibss(local, sdata);
 	mutex_lock(&local->mtx);
-	ieee80211_vif_release_channel(sdata);
+	ieee80211_link_release_channel(sdata->link[0]);
 	mutex_unlock(&local->mtx);
 }
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 397b111f006d..92ed1e3c2980 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -787,8 +787,8 @@ struct ieee80211_chanctx {
 	struct list_head list;
 	struct rcu_head rcu_head;
 
-	struct list_head assigned_vifs;
-	struct list_head reserved_vifs;
+	struct list_head assigned_links;
+	struct list_head reserved_links;
 
 	enum ieee80211_chanctx_replace_state replace_state;
 	struct ieee80211_chanctx *replace_ctx;
@@ -909,6 +909,12 @@ struct ieee80211_link_data_ap {
 };
 
 struct ieee80211_link_data {
+	struct ieee80211_sub_if_data *sdata;
+	unsigned int link_id;
+
+	struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */
+	struct list_head reserved_chanctx_list; /* protected by chanctx_mtx */
+
 	/* multicast keys only */
 	struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS +
 					NUM_DEFAULT_MGMT_KEYS +
@@ -989,9 +995,6 @@ struct ieee80211_sub_if_data {
 	struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
 	struct mac80211_qos_map __rcu *qos_map;
 
-	struct list_head assigned_chanctx_list; /* protected by chanctx_mtx */
-	struct list_head reserved_chanctx_list; /* protected by chanctx_mtx */
-
 	/* used to reconfigure hardware SM PS */
 	struct work_struct recalc_smps;
 
@@ -2119,8 +2122,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 				    struct ieee80211_supported_band *sband,
 				    const struct ieee80211_vht_cap *vht_cap_ie,
 				    struct sta_info *sta);
-enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta);
-enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
+enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta,
+							unsigned int link_id);
+enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta,
+							 unsigned int link_id);
 void ieee80211_sta_set_rx_nss(struct sta_info *sta);
 enum ieee80211_sta_rx_bandwidth
 ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width);
@@ -2470,26 +2475,26 @@ bool ieee80211_chandef_s1g_oper(const struct ieee80211_s1g_oper_ie *oper,
 u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c);
 
 int __must_check
-ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
-			  const struct cfg80211_chan_def *chandef,
-			  enum ieee80211_chanctx_mode mode);
+ieee80211_link_use_channel(struct ieee80211_link_data *link,
+			   const struct cfg80211_chan_def *chandef,
+			   enum ieee80211_chanctx_mode mode);
 int __must_check
-ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata,
-			      const struct cfg80211_chan_def *chandef,
-			      enum ieee80211_chanctx_mode mode,
-			      bool radar_required);
+ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
+			       const struct cfg80211_chan_def *chandef,
+			       enum ieee80211_chanctx_mode mode,
+			       bool radar_required);
 int __must_check
-ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata);
-int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata);
+ieee80211_link_use_reserved_context(struct ieee80211_link_data *link);
+int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link);
 
 int __must_check
-ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
-			       const struct cfg80211_chan_def *chandef,
-			       u32 *changed);
-void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
-void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
-void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
-					 bool clear);
+ieee80211_link_change_bandwidth(struct ieee80211_link_data *link,
+				const struct cfg80211_chan_def *chandef,
+				u32 *changed);
+void ieee80211_link_release_channel(struct ieee80211_link_data *link);
+void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link);
+void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
+					  bool clear);
 int ieee80211_chanctx_refcount(struct ieee80211_local *local,
 			       struct ieee80211_chanctx *ctx);
 
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 04ee525394e9..1764068a18d1 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -471,7 +471,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
 		chandef = sdata->vif.bss_conf.chandef;
 		WARN_ON(local->suspended);
 		mutex_lock(&local->mtx);
-		ieee80211_vif_release_channel(sdata);
+		ieee80211_link_release_channel(sdata->link[0]);
 		mutex_unlock(&local->mtx);
 		cfg80211_cac_event(sdata->dev, &chandef,
 				   NL80211_RADAR_CAC_ABORTED,
@@ -1027,6 +1027,7 @@ static void ieee80211_sdata_init(struct ieee80211_local *local,
 	 */
 	sdata->vif.link_conf[0] = &sdata->vif.bss_conf;
 	sdata->link[0] = &sdata->deflink;
+	sdata->deflink.sdata = sdata;
 }
 
 int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
@@ -1077,8 +1078,8 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 	mutex_unlock(&local->iflist_mtx);
 
 	mutex_lock(&local->mtx);
-	ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
-					IEEE80211_CHANCTX_EXCLUSIVE);
+	ret = ieee80211_link_use_channel(sdata->link[0], &local->monitor_chandef,
+					 IEEE80211_CHANCTX_EXCLUSIVE);
 	mutex_unlock(&local->mtx);
 	if (ret) {
 		mutex_lock(&local->iflist_mtx);
@@ -1122,7 +1123,7 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
 	synchronize_net();
 
 	mutex_lock(&local->mtx);
-	ieee80211_vif_release_channel(sdata);
+	ieee80211_link_release_channel(sdata->link[0]);
 	mutex_unlock(&local->mtx);
 
 	drv_remove_interface(local, sdata);
@@ -1228,7 +1229,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 	case NL80211_IFTYPE_AP_VLAN:
 		/* no need to tell driver, but set carrier and chanctx */
 		if (sdata->bss->active) {
-			ieee80211_vif_vlan_copy_chanctx(sdata);
+			ieee80211_link_vlan_copy_chanctx(sdata->link[0]);
 			netif_carrier_on(dev);
 			ieee80211_set_vif_encap_ops(sdata);
 		} else {
@@ -1681,8 +1682,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 		  ieee80211_csa_finalize_work);
 	INIT_WORK(&sdata->deflink.color_change_finalize_work,
 		  ieee80211_color_change_finalize_work);
-	INIT_LIST_HEAD(&sdata->assigned_chanctx_list);
-	INIT_LIST_HEAD(&sdata->reserved_chanctx_list);
+	INIT_LIST_HEAD(&sdata->deflink.assigned_chanctx_list);
+	INIT_LIST_HEAD(&sdata->deflink.reserved_chanctx_list);
 
 	switch (type) {
 	case NL80211_IFTYPE_P2P_GO:
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 42ba7424589e..a6cb1db50f1d 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2008, 2009 open80211s Ltd.
- * Copyright (C) 2019, 2021 Intel Corporation
+ * Copyright (C) 2019, 2021-2022 Intel Corporation
  * Author:     Luis Carlos Cobo <luisca@cozybit.com>
  */
 #include <linux/gfp.h>
@@ -464,7 +464,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 	if (!test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
 		rate_control_rate_init(sta);
 	else
-		rate_control_rate_update(local, sband, sta, changed);
+		rate_control_rate_update(local, sband, sta, 0, changed);
 out:
 	spin_unlock_bh(&sta->mesh->plink_lock);
 }
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e172bdfe9b0a..ca9e0d83e2a4 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -479,7 +479,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
 		return -EINVAL;
 	}
 
-	ret = ieee80211_vif_change_bandwidth(sdata, &chandef, changed);
+	ret = ieee80211_link_change_bandwidth(&sdata->deflink, &chandef, changed);
 
 	if (ret) {
 		sdata_info(sdata,
@@ -1248,7 +1248,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 		if (sdata->deflink.reserved_ready)
 			goto out;
 
-		ret = ieee80211_vif_use_reserved_context(sdata);
+		ret = ieee80211_link_use_reserved_context(&sdata->deflink);
 		if (ret) {
 			sdata_info(sdata,
 				   "failed to use reserved channel context, disconnecting (err=%d)\n",
@@ -1354,7 +1354,7 @@ ieee80211_sta_abort_chanswitch(struct ieee80211_sub_if_data *sdata)
 	mutex_lock(&local->mtx);
 
 	mutex_lock(&local->chanctx_mtx);
-	ieee80211_vif_unreserve_chanctx(sdata);
+	ieee80211_link_unreserve_chanctx(&sdata->deflink);
 	mutex_unlock(&local->chanctx_mtx);
 
 	if (sdata->deflink.csa_block_tx)
@@ -1496,8 +1496,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 		goto drop_connection;
 	}
 
-	res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef,
-					    chanctx->mode, false);
+	res = ieee80211_link_reserve_chanctx(&sdata->deflink, &csa_ie.chandef,
+					     chanctx->mode, false);
 	if (res) {
 		sdata_info(sdata,
 			   "failed to reserve channel context for channel switch, disconnecting (err=%d)\n",
@@ -1942,7 +1942,7 @@ void ieee80211_dfs_cac_timer_work(struct work_struct *work)
 
 	mutex_lock(&sdata->local->mtx);
 	if (sdata->wdev.cac_started) {
-		ieee80211_vif_release_channel(sdata);
+		ieee80211_link_release_channel(&sdata->deflink);
 		cfg80211_cac_event(sdata->dev, &chandef,
 				   NL80211_RADAR_CAC_FINISHED,
 				   GFP_KERNEL);
@@ -2483,7 +2483,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 
 	ifmgd->flags = 0;
 	mutex_lock(&local->mtx);
-	ieee80211_vif_release_channel(sdata);
+	ieee80211_link_release_channel(&sdata->deflink);
 
 	sdata->vif.bss_conf.csa_active = false;
 	sdata->deflink.u.mgd.csa_waiting_bcn = false;
@@ -2923,7 +2923,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
 		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_BSSID);
 		sdata->u.mgd.flags = 0;
 		mutex_lock(&sdata->local->mtx);
-		ieee80211_vif_release_channel(sdata);
+		ieee80211_link_release_channel(&sdata->deflink);
 		mutex_unlock(&sdata->local->mtx);
 	}
 
@@ -2954,7 +2954,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
 		sdata->vif.bss_conf.mu_mimo_owner = false;
 
 		mutex_lock(&sdata->local->mtx);
-		ieee80211_vif_release_channel(sdata);
+		ieee80211_link_release_channel(&sdata->deflink);
 		mutex_unlock(&sdata->local->mtx);
 
 		if (abandon)
@@ -5497,8 +5497,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
 	 * on incompatible channels, e.g. 80+80 and 160 sharing the
 	 * same control channel) try to use a smaller bandwidth.
 	 */
-	ret = ieee80211_vif_use_channel(sdata, &chandef,
-					IEEE80211_CHANCTX_SHARED);
+	ret = ieee80211_link_use_channel(&sdata->deflink, &chandef,
+					 IEEE80211_CHANCTX_SHARED);
 
 	/* don't downgrade for 5 and 10 MHz channels, though. */
 	if (chandef.width == NL80211_CHAN_WIDTH_5 ||
@@ -5507,8 +5507,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
 
 	while (ret && chandef.width != NL80211_CHAN_WIDTH_20_NOHT) {
 		ifmgd->flags |= ieee80211_chandef_downgrade(&chandef);
-		ret = ieee80211_vif_use_channel(sdata, &chandef,
-						IEEE80211_CHANCTX_SHARED);
+		ret = ieee80211_link_use_channel(&sdata->deflink, &chandef,
+						 IEEE80211_CHANCTX_SHARED);
 	}
  out:
 	mutex_unlock(&local->mtx);
@@ -5868,7 +5868,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_BSSID);
 	ifmgd->auth_data = NULL;
 	mutex_lock(&sdata->local->mtx);
-	ieee80211_vif_release_channel(sdata);
+	ieee80211_link_release_channel(&sdata->deflink);
 	mutex_unlock(&sdata->local->mtx);
 	kfree(auth_data);
 	return err;
diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c
index ab2658ad73ce..468c741a9aeb 100644
--- a/net/mac80211/ocb.c
+++ b/net/mac80211/ocb.c
@@ -186,8 +186,8 @@ int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
 	sdata->deflink.needed_rx_chains = sdata->local->rx_chains;
 
 	mutex_lock(&sdata->local->mtx);
-	err = ieee80211_vif_use_channel(sdata, &setup->chandef,
-					IEEE80211_CHANCTX_SHARED);
+	err = ieee80211_link_use_channel(sdata->link[0], &setup->chandef,
+					 IEEE80211_CHANCTX_SHARED);
 	mutex_unlock(&sdata->local->mtx);
 	if (err)
 		return err;
@@ -229,7 +229,7 @@ int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata)
 	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_OCB);
 
 	mutex_lock(&sdata->local->mtx);
-	ieee80211_vif_release_channel(sdata);
+	ieee80211_link_release_channel(sdata->link[0]);
 	mutex_unlock(&sdata->local->mtx);
 
 	skb_queue_purge(&sdata->skb_queue);
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index f22381127948..b268088585eb 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -90,14 +90,17 @@ void rate_control_tx_status(struct ieee80211_local *local,
 }
 
 void rate_control_rate_update(struct ieee80211_local *local,
-				    struct ieee80211_supported_band *sband,
-				    struct sta_info *sta, u32 changed)
+			      struct ieee80211_supported_band *sband,
+			      struct sta_info *sta, unsigned int link_id,
+			      u32 changed)
 {
 	struct rate_control_ref *ref = local->rate_ctrl;
 	struct ieee80211_sta *ista = &sta->sta;
 	void *priv_sta = sta->rate_ctrl_priv;
 	struct ieee80211_chanctx_conf *chanctx_conf;
 
+	WARN_ON(link_id != 0);
+
 	if (ref && ref->ops->rate_update) {
 		rcu_read_lock();
 
@@ -113,6 +116,7 @@ void rate_control_rate_update(struct ieee80211_local *local,
 		spin_unlock_bh(&sta->rate_ctrl_lock);
 		rcu_read_unlock();
 	}
+
 	drv_sta_rc_update(local, sta->sdata, &sta->sta, changed);
 }
 
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 79b44d3db171..fbc8bdb54c43 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -3,6 +3,7 @@
  * Copyright 2002-2005, Instant802 Networks, Inc.
  * Copyright 2005, Devicescape Software, Inc.
  * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ * Copyright (C) 2022 Intel Corporation
  */
 
 #ifndef IEEE80211_RATE_H
@@ -31,8 +32,10 @@ void rate_control_tx_status(struct ieee80211_local *local,
 
 void rate_control_rate_init(struct sta_info *sta);
 void rate_control_rate_update(struct ieee80211_local *local,
-				    struct ieee80211_supported_band *sband,
-				    struct sta_info *sta, u32 changed);
+			      struct ieee80211_supported_band *sband,
+			      struct sta_info *sta,
+			      unsigned int link_id,
+			      u32 changed);
 
 static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
 					   struct sta_info *sta, gfp_t gfp)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 21e7424f261a..1774d0f9feaa 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3369,7 +3369,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 
 			sband = rx->local->hw.wiphy->bands[status->band];
 
-			rate_control_rate_update(local, sband, rx->sta,
+			rate_control_rate_update(local, sband, rx->sta, 0,
 						 IEEE80211_RC_SMPS_CHANGED);
 			cfg80211_sta_opmode_change_notify(sdata->dev,
 							  rx->sta->addr,
@@ -3391,11 +3391,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 			if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ)
 				max_bw = IEEE80211_STA_RX_BW_20;
 			else
-				max_bw = ieee80211_sta_cap_rx_bw(rx->sta);
+				max_bw = ieee80211_sta_cap_rx_bw(rx->sta, 0);
 
 			/* set cur_max_bandwidth and recalc sta bw */
 			rx->sta->deflink.cur_max_bandwidth = max_bw;
-			new_bw = ieee80211_sta_cur_vht_bw(rx->sta);
+			new_bw = ieee80211_sta_cur_vht_bw(rx->sta, 0);
 
 			if (rx->sta->sta.deflink.bandwidth == new_bw)
 				goto handled;
@@ -3406,7 +3406,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 				ieee80211_sta_rx_bw_to_chan_width(rx->sta);
 			sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED;
 
-			rate_control_rate_update(local, sband, rx->sta,
+			rate_control_rate_update(local, sband, rx->sta, 0,
 						 IEEE80211_RC_BW_CHANGED);
 			cfg80211_sta_opmode_change_notify(sdata->dev,
 							  rx->sta->addr,
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 11a3b950b490..86a13ef31ef1 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -1268,10 +1268,10 @@ static void iee80211_tdls_recalc_chanctx(struct ieee80211_sub_if_data *sdata,
 			enum ieee80211_sta_rx_bandwidth bw;
 
 			bw = ieee80211_chan_width_to_rx_bw(conf->def.width);
-			bw = min(bw, ieee80211_sta_cap_rx_bw(sta));
+			bw = min(bw, ieee80211_sta_cap_rx_bw(sta, 0));
 			if (bw != sta->sta.deflink.bandwidth) {
 				sta->sta.deflink.bandwidth = bw;
-				rate_control_rate_update(local, sband, sta,
+				rate_control_rate_update(local, sband, sta, 0,
 							 IEEE80211_RC_BW_CHANGED);
 				/*
 				 * if a TDLS peer BW was updated, we need to
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 7284f0bf8a99..5c941fe4d70a 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1625,6 +1625,7 @@ struct trace_chandef_entry {
 
 struct trace_switch_entry {
 	struct trace_vif_entry vif;
+	unsigned int link_id;
 	struct trace_chandef_entry old_chandef;
 	struct trace_chandef_entry new_chandef;
 } __packed;
@@ -1664,6 +1665,7 @@ TRACE_EVENT(drv_switch_vif_chanctx,
 
 				SWITCH_ENTRY_ASSIGN(vif.vif_type, vif->type);
 				SWITCH_ENTRY_ASSIGN(vif.p2p, vif->p2p);
+				SWITCH_ENTRY_ASSIGN(link_id, link_id);
 				strncpy(local_vifs[i].vif.vif_name,
 					sdata->name,
 					sizeof(local_vifs[i].vif.vif_name));
@@ -1704,40 +1706,45 @@ TRACE_EVENT(drv_switch_vif_chanctx,
 DECLARE_EVENT_CLASS(local_sdata_chanctx,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata,
+		 unsigned int link_id,
 		 struct ieee80211_chanctx *ctx),
 
-	TP_ARGS(local, sdata, ctx),
+	TP_ARGS(local, sdata, link_id, ctx),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
 		VIF_ENTRY
 		CHANCTX_ENTRY
+		__field(unsigned int, link_id)
 	),
 
 	TP_fast_assign(
 		LOCAL_ASSIGN;
 		VIF_ASSIGN;
 		CHANCTX_ASSIGN;
+		__entry->link_id = link_id;
 	),
 
 	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT CHANCTX_PR_FMT,
-		LOCAL_PR_ARG, VIF_PR_ARG, CHANCTX_PR_ARG
+		LOCAL_PR_FMT VIF_PR_FMT " link_id:%d" CHANCTX_PR_FMT,
+		LOCAL_PR_ARG, VIF_PR_ARG, __entry->link_id, CHANCTX_PR_ARG
 	)
 );
 
 DEFINE_EVENT(local_sdata_chanctx, drv_assign_vif_chanctx,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata,
+		 unsigned int link_id,
 		 struct ieee80211_chanctx *ctx),
-	TP_ARGS(local, sdata, ctx)
+	TP_ARGS(local, sdata, link_id, ctx)
 );
 
 DEFINE_EVENT(local_sdata_chanctx, drv_unassign_vif_chanctx,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sub_if_data *sdata,
+		 unsigned int link_id,
 		 struct ieee80211_chanctx *ctx),
-	TP_ARGS(local, sdata, ctx)
+	TP_ARGS(local, sdata, link_id, ctx)
 );
 
 TRACE_EVENT(drv_start_ap,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2a279dc3e457..4ec96170a679 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2255,7 +2255,8 @@ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
 }
 
 static void ieee80211_assign_chanctx(struct ieee80211_local *local,
-				     struct ieee80211_sub_if_data *sdata)
+				     struct ieee80211_sub_if_data *sdata,
+				     unsigned int link_id)
 {
 	struct ieee80211_chanctx_conf *conf;
 	struct ieee80211_chanctx *ctx;
@@ -2264,11 +2265,11 @@ static void ieee80211_assign_chanctx(struct ieee80211_local *local,
 		return;
 
 	mutex_lock(&local->chanctx_mtx);
-	conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf,
+	conf = rcu_dereference_protected(sdata->vif.link_conf[link_id]->chanctx_conf,
 					 lockdep_is_held(&local->chanctx_mtx));
 	if (conf) {
 		ctx = container_of(conf, struct ieee80211_chanctx, conf);
-		drv_assign_vif_chanctx(local, sdata, ctx);
+		drv_assign_vif_chanctx(local, sdata, link_id, ctx);
 	}
 	mutex_unlock(&local->chanctx_mtx);
 }
@@ -2474,7 +2475,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 		sdata = wiphy_dereference(local->hw.wiphy,
 					  local->monitor_sdata);
 		if (sdata && ieee80211_sdata_running(sdata))
-			ieee80211_assign_chanctx(local, sdata);
+			ieee80211_assign_chanctx(local, sdata, 0);
 	}
 
 	/* reconfigure hardware */
@@ -2484,12 +2485,16 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 
 	/* Finally also reconfigure all the BSS information */
 	list_for_each_entry(sdata, &local->interfaces, list) {
+		unsigned int link;
 		u32 changed;
 
 		if (!ieee80211_sdata_running(sdata))
 			continue;
 
-		ieee80211_assign_chanctx(local, sdata);
+		for (link = 0; link < ARRAY_SIZE(sdata->vif.link_conf); link++) {
+			if (sdata->vif.link_conf[link])
+				ieee80211_assign_chanctx(local, sdata, link);
+		}
 
 		switch (sdata->vif.type) {
 		case NL80211_IFTYPE_AP_VLAN:
@@ -3975,7 +3980,7 @@ void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
 
 		if (sdata->wdev.cac_started) {
 			chandef = sdata->vif.bss_conf.chandef;
-			ieee80211_vif_release_channel(sdata);
+			ieee80211_link_release_channel(sdata->link[0]);
 			cfg80211_cac_event(sdata->dev,
 					   &chandef,
 					   NL80211_RADAR_CAC_ABORTED,
@@ -4401,7 +4406,7 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local,
 static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local,
 					 struct ieee80211_chanctx *ctx)
 {
-	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_link_data *link;
 	u8 radar_detect = 0;
 
 	lockdep_assert_held(&local->chanctx_mtx);
@@ -4409,20 +4414,26 @@ static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local,
 	if (WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED))
 		return 0;
 
-	list_for_each_entry(sdata, &ctx->reserved_vifs, reserved_chanctx_list)
-		if (sdata->deflink.reserved_radar_required)
-			radar_detect |= BIT(sdata->deflink.reserved_chandef.width);
+	list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list)
+		if (link->reserved_radar_required)
+			radar_detect |= BIT(link->reserved_chandef.width);
 
 	/*
 	 * An in-place reservation context should not have any assigned vifs
 	 * until it replaces the other context.
 	 */
 	WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
-		!list_empty(&ctx->assigned_vifs));
+		!list_empty(&ctx->assigned_links));
+
+	list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) {
+		struct ieee80211_sub_if_data *sdata = link->sdata;
 
-	list_for_each_entry(sdata, &ctx->assigned_vifs, assigned_chanctx_list)
-		if (sdata->deflink.radar_required)
-			radar_detect |= BIT(sdata->vif.bss_conf.chandef.width);
+		if (!link->radar_required)
+			continue;
+
+		radar_detect |=
+			BIT(sdata->vif.link_conf[link->link_id]->chandef.width);
+	}
 
 	return radar_detect;
 }
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 7daca8352deb..27d260be9123 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -313,7 +313,7 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 			sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
 	}
 
-	sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta);
+	sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta, 0);
 
 	switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
 	case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
@@ -330,19 +330,21 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 }
 
 /* FIXME: move this to some better location - parses HE/EHT now */
-enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
+enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta,
+							unsigned int link_id)
 {
-	struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.deflink.vht_cap;
-	struct ieee80211_sta_he_cap *he_cap = &sta->sta.deflink.he_cap;
-	struct ieee80211_sta_eht_cap *eht_cap = &sta->sta.deflink.eht_cap;
+	struct ieee80211_bss_conf *link_conf = sta->sdata->vif.link_conf[link_id];
+	struct ieee80211_link_sta *link_sta = sta->sta.link[link_id];
+	struct ieee80211_sta_vht_cap *vht_cap = &link_sta->vht_cap;
+	struct ieee80211_sta_he_cap *he_cap = &link_sta->he_cap;
+	struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap;
 	u32 cap_width;
 
 	if (he_cap->has_he) {
 		u8 info;
 
 		if (eht_cap->has_eht &&
-		    sta->sdata->vif.bss_conf.chandef.chan->band ==
-		    NL80211_BAND_6GHZ) {
+		    link_conf->chandef.chan->band == NL80211_BAND_6GHZ) {
 			info = eht_cap->eht_cap_elem.phy_cap_info[0];
 
 			if (info & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
@@ -351,8 +353,7 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
 
 		info = he_cap->he_cap_elem.phy_cap_info[0];
 
-		if (sta->sdata->vif.bss_conf.chandef.chan->band ==
-				NL80211_BAND_2GHZ) {
+		if (link_conf->chandef.chan->band == NL80211_BAND_2GHZ) {
 			if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G)
 				return IEEE80211_STA_RX_BW_40;
 			else
@@ -369,7 +370,7 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta)
 	}
 
 	if (!vht_cap->vht_supported)
-		return sta->sta.deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
+		return link_sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
 				IEEE80211_STA_RX_BW_40 :
 				IEEE80211_STA_RX_BW_20;
 
@@ -466,14 +467,15 @@ ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width)
 }
 
 /* FIXME: rename/move - this deals with everything not just VHT */
-enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
+enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta,
+							 unsigned int link_id)
 {
-	struct ieee80211_sub_if_data *sdata = sta->sdata;
+	struct ieee80211_bss_conf *link_conf = sta->sdata->vif.link_conf[link_id];
+	enum nl80211_chan_width bss_width = link_conf->chandef.width;
 	enum ieee80211_sta_rx_bandwidth bw;
-	enum nl80211_chan_width bss_width = sdata->vif.bss_conf.chandef.width;
 
-	bw = ieee80211_sta_cap_rx_bw(sta);
-	bw = min(bw, sta->deflink.cur_max_bandwidth);
+	bw = ieee80211_sta_cap_rx_bw(sta, link_id);
+	bw = min(bw, sta->link[link_id]->cur_max_bandwidth);
 
 	/* Don't consider AP's bandwidth for TDLS peers, section 11.23.1 of
 	 * IEEE80211-2016 specification makes higher bandwidth operation
@@ -629,7 +631,7 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 		break;
 	}
 
-	new_bw = ieee80211_sta_cur_vht_bw(sta);
+	new_bw = ieee80211_sta_cur_vht_bw(sta, 0);
 	if (new_bw != sta->sta.deflink.bandwidth) {
 		sta->sta.deflink.bandwidth = new_bw;
 		sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta);
@@ -692,7 +694,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 
 	if (changed > 0) {
 		ieee80211_recalc_min_chandef(sdata);
-		rate_control_rate_update(local, sband, sta, changed);
+		rate_control_rate_update(local, sband, sta, 0, changed);
 	}
 }
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 05/15] mac80211: remove sta_info_tx_streams()
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (3 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 04/15] mac80211: make channel context code MLO-aware Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 06/15] mac80211: refactor some sta_info link handling Johannes Berg
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

The function is unused since commit 52b4810bed83 ("mac80211: Remove
support for changing AP SMPS mode") so we can just remove it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/sta_info.c | 35 -----------------------------------
 net/mac80211/sta_info.h |  1 -
 2 files changed, 36 deletions(-)

diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 9a70d846d0dd..6f6d83def8b8 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2093,41 +2093,6 @@ int sta_info_move_state(struct sta_info *sta,
 	return 0;
 }
 
-u8 sta_info_tx_streams(struct sta_info *sta)
-{
-	struct ieee80211_sta_ht_cap *ht_cap = &sta->sta.deflink.ht_cap;
-	u8 rx_streams;
-
-	if (!sta->sta.deflink.ht_cap.ht_supported)
-		return 1;
-
-	if (sta->sta.deflink.vht_cap.vht_supported) {
-		int i;
-		u16 tx_mcs_map =
-			le16_to_cpu(sta->sta.deflink.vht_cap.vht_mcs.tx_mcs_map);
-
-		for (i = 7; i >= 0; i--)
-			if ((tx_mcs_map & (0x3 << (i * 2))) !=
-			    IEEE80211_VHT_MCS_NOT_SUPPORTED)
-				return i + 1;
-	}
-
-	if (ht_cap->mcs.rx_mask[3])
-		rx_streams = 4;
-	else if (ht_cap->mcs.rx_mask[2])
-		rx_streams = 3;
-	else if (ht_cap->mcs.rx_mask[1])
-		rx_streams = 2;
-	else
-		rx_streams = 1;
-
-	if (!(ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_RX_DIFF))
-		return rx_streams;
-
-	return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
-			>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
-}
-
 static struct ieee80211_sta_rx_stats *
 sta_get_last_rx_stats(struct sta_info *sta)
 {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index aa6950aa49a9..134a7dad0ac4 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -891,7 +891,6 @@ u32 sta_get_expected_throughput(struct sta_info *sta);
 
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
 			  unsigned long exp_time);
-u8 sta_info_tx_streams(struct sta_info *sta);
 
 void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 06/15] mac80211: refactor some sta_info link handling
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (4 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 05/15] mac80211: remove sta_info_tx_streams() Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 07/15] mac80211: use IEEE80211_MLD_MAX_NUM_LINKS Johannes Berg
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Refactor the code a bit to initialize a link belonging
to a station, and (later) free all allocated links.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/sta_info.c | 79 +++++++++++++++++++++++++++++------------
 1 file changed, 56 insertions(+), 23 deletions(-)

diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 6f6d83def8b8..f20ce7bbcb39 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -245,6 +245,20 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
 	return NULL;
 }
 
+static void sta_info_free_links(struct sta_info *sta)
+{
+	unsigned int link_id;
+
+	for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
+		if (!sta->link[link_id])
+			continue;
+		free_percpu(sta->link[link_id]->pcpu_rx_stats);
+
+		if (sta->link[link_id] != &sta->deflink)
+			kfree(sta->link[link_id]);
+	}
+}
+
 /**
  * sta_info_free - free STA
  *
@@ -287,7 +301,8 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
 #ifdef CONFIG_MAC80211_MESH
 	kfree(sta->mesh);
 #endif
-	free_percpu(sta->deflink.pcpu_rx_stats);
+
+	sta_info_free_links(sta);
 	kfree(sta);
 }
 
@@ -333,6 +348,40 @@ static int sta_prepare_rate_control(struct ieee80211_local *local,
 	return 0;
 }
 
+static int sta_info_init_link(struct sta_info *sta,
+			      unsigned int link_id,
+			      struct link_sta_info *link_info,
+			      struct ieee80211_link_sta *link_sta,
+			      gfp_t gfp)
+{
+	struct ieee80211_local *local = sta->local;
+	struct ieee80211_hw *hw = &local->hw;
+	int i;
+
+	link_info->sta = sta;
+	link_info->link_id = link_id;
+
+	if (ieee80211_hw_check(hw, USES_RSS)) {
+		link_info->pcpu_rx_stats =
+			alloc_percpu_gfp(struct ieee80211_sta_rx_stats, gfp);
+		if (!link_info->pcpu_rx_stats)
+			return -ENOMEM;
+	}
+
+	sta->link[link_id] = link_info;
+	sta->sta.link[link_id] = link_sta;
+
+	link_info->rx_stats.last_rx = jiffies;
+	u64_stats_init(&link_info->rx_stats.syncp);
+
+	ewma_signal_init(&link_info->rx_stats_avg.signal);
+	ewma_avg_signal_init(&link_info->status_stats.avg_ack_signal);
+	for (i = 0; i < ARRAY_SIZE(link_info->rx_stats_avg.chain_signal); i++)
+		ewma_signal_init(&link_info->rx_stats_avg.chain_signal[i]);
+
+	return 0;
+}
+
 struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 				const u8 *addr, gfp_t gfp)
 {
@@ -345,12 +394,11 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 	if (!sta)
 		return NULL;
 
-	if (ieee80211_hw_check(hw, USES_RSS)) {
-		sta->deflink.pcpu_rx_stats =
-			alloc_percpu_gfp(struct ieee80211_sta_rx_stats, gfp);
-		if (!sta->deflink.pcpu_rx_stats)
-			goto free;
-	}
+	sta->local = local;
+	sta->sdata = sdata;
+
+	if (sta_info_init_link(sta, 0, &sta->deflink, &sta->sta.deflink, gfp))
+		return NULL;
 
 	spin_lock_init(&sta->lock);
 	spin_lock_init(&sta->ps_lock);
@@ -378,12 +426,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 
 	/* TODO link specific alloc and assignments for MLO Link STA */
 
-	/* For non MLO STA, link info can be accessed either via deflink
-	 * or link[0]
-	 */
-	sta->link[0] = &sta->deflink;
-	sta->sta.link[0] = &sta->sta.deflink;
-
 	/* Extended Key ID needs to install keys for keyid 0 and 1 Rx-only.
 	 * The Tx path starts to use a key as soon as the key slot ptk_idx
 	 * references to is not NULL. To not use the initial Rx-only key
@@ -393,11 +435,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 	BUILD_BUG_ON(ARRAY_SIZE(sta->ptk) <= INVALID_PTK_KEYIDX);
 	sta->ptk_idx = INVALID_PTK_KEYIDX;
 
-	sta->local = local;
-	sta->sdata = sdata;
-	sta->deflink.rx_stats.last_rx = jiffies;
-
-	u64_stats_init(&sta->deflink.rx_stats.syncp);
 
 	ieee80211_init_frag_cache(&sta->frags);
 
@@ -407,10 +444,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 	sta->reserved_tid = IEEE80211_TID_UNRESERVED;
 
 	sta->last_connected = ktime_get_seconds();
-	ewma_signal_init(&sta->deflink.rx_stats_avg.signal);
-	ewma_avg_signal_init(&sta->deflink.status_stats.avg_ack_signal);
-	for (i = 0; i < ARRAY_SIZE(sta->deflink.rx_stats_avg.chain_signal); i++)
-		ewma_signal_init(&sta->deflink.rx_stats_avg.chain_signal[i]);
 
 	if (local->ops->wake_tx_queue) {
 		void *txq_data;
@@ -532,7 +565,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 	if (sta->sta.txq[0])
 		kfree(to_txq_info(sta->sta.txq[0]));
 free:
-	free_percpu(sta->deflink.pcpu_rx_stats);
+	sta_info_free_links(sta);
 #ifdef CONFIG_MAC80211_MESH
 	kfree(sta->mesh);
 #endif
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 07/15] mac80211: use IEEE80211_MLD_MAX_NUM_LINKS
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (5 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 06/15] mac80211: refactor some sta_info link handling Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 08/15] mac80211: validate some driver features for MLO Johannes Berg
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Remove MAX_STA_LINKS and use IEEE80211_MLD_MAX_NUM_LINKS
instead to unify between the station and other data structures.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h  | 4 +---
 net/mac80211/sta_info.h | 2 +-
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4b3d19d88954..66a18dc4462f 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2061,8 +2061,6 @@ struct ieee80211_sta_txpwr {
 	enum nl80211_tx_power_setting type;
 };
 
-#define MAX_STA_LINKS			15
-
 /**
  * struct ieee80211_link_sta - station Link specific info
  * All link specific info for a STA link for a non MLD STA(single)
@@ -2190,7 +2188,7 @@ struct ieee80211_sta {
 
 	bool multi_link_sta;
 	struct ieee80211_link_sta deflink;
-	struct ieee80211_link_sta *link[MAX_STA_LINKS];
+	struct ieee80211_link_sta *link[IEEE80211_MLD_MAX_NUM_LINKS];
 
 	/* must be last */
 	u8 drv_priv[] __aligned(sizeof(void *));
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 134a7dad0ac4..2ff3d5fd0cbf 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -710,7 +710,7 @@ struct sta_info {
 
 	bool multi_link_sta;
 	struct link_sta_info deflink;
-	struct link_sta_info *link[MAX_STA_LINKS];
+	struct link_sta_info *link[IEEE80211_MLD_MAX_NUM_LINKS];
 
 	/* keep last! */
 	struct ieee80211_sta sta;
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 08/15] mac80211: validate some driver features for MLO
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (6 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 07/15] mac80211: use IEEE80211_MLD_MAX_NUM_LINKS Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 09/15] mac80211: refactor some link setup code Johannes Berg
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

If MLO is enabled by the driver then validate a set of
capabilities that mac80211 will initially not support
in MLO. This might change if features are implemented.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/main.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6165b90bf0e2..c5553d68d779 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -951,6 +951,48 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 		    (!local->ops->start_nan || !local->ops->stop_nan)))
 		return -EINVAL;
 
+	if (hw->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO) {
+		/*
+		 * For drivers capable of doing MLO, assume modern driver
+		 * or firmware facilities, so software doesn't have to do
+		 * as much, e.g. monitoring beacons would be hard if we
+		 * might not even know which link is active at which time.
+		 */
+		if (WARN_ON(!local->use_chanctx))
+			return -EINVAL;
+
+		if (WARN_ON(!local->ops->link_info_changed))
+			return -EINVAL;
+
+		if (WARN_ON(!ieee80211_hw_check(hw, HAS_RATE_CONTROL)))
+			return -EINVAL;
+
+		if (WARN_ON(!ieee80211_hw_check(hw, AMPDU_AGGREGATION)))
+			return -EINVAL;
+
+		if (WARN_ON(ieee80211_hw_check(hw, HOST_BROADCAST_PS_BUFFERING)))
+			return -EINVAL;
+
+		if (WARN_ON(ieee80211_hw_check(hw, SUPPORTS_PS) &&
+			    !ieee80211_hw_check(hw, SUPPORTS_DYNAMIC_PS)))
+			return -EINVAL;
+
+		if (WARN_ON(!ieee80211_hw_check(hw, MFP_CAPABLE)))
+			return -EINVAL;
+
+		if (WARN_ON(!ieee80211_hw_check(hw, CONNECTION_MONITOR)))
+			return -EINVAL;
+
+		if (WARN_ON(ieee80211_hw_check(hw, NEED_DTIM_BEFORE_ASSOC)))
+			return -EINVAL;
+
+		if (WARN_ON(ieee80211_hw_check(hw, TIMING_BEACON_ONLY)))
+			return -EINVAL;
+
+		if (WARN_ON(!ieee80211_hw_check(hw, AP_LINK_PS)))
+			return -EINVAL;
+	}
+
 #ifdef CONFIG_PM
 	if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume))
 		return -EINVAL;
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 09/15] mac80211: refactor some link setup code
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (7 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 08/15] mac80211: validate some driver features for MLO Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 10/15] mac80211: add link_id to vht.c code for MLO Johannes Berg
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

We don't need to setup lists and work structs every time
we switch the interface type, factor that out into a new
ieee80211_link_init() function and use it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/iface.c | 33 ++++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 1764068a18d1..fa684d76a169 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1012,6 +1012,27 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
 	sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
 }
 
+static void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
+				unsigned int link_id,
+				struct ieee80211_link_data *link,
+				struct ieee80211_bss_conf *link_conf)
+{
+	sdata->vif.link_conf[link_id] = link_conf;
+	sdata->link[link_id] = link;
+
+	link->sdata = sdata;
+	link->link_id = link_id;
+
+	INIT_WORK(&link->csa_finalize_work,
+		  ieee80211_csa_finalize_work);
+	INIT_WORK(&link->color_change_finalize_work,
+		  ieee80211_color_change_finalize_work);
+	INIT_LIST_HEAD(&link->assigned_chanctx_list);
+	INIT_LIST_HEAD(&link->reserved_chanctx_list);
+	INIT_DELAYED_WORK(&link->dfs_cac_timer_work,
+			  ieee80211_dfs_cac_timer_work);
+}
+
 static void ieee80211_sdata_init(struct ieee80211_local *local,
 				 struct ieee80211_sub_if_data *sdata)
 {
@@ -1025,9 +1046,7 @@ static void ieee80211_sdata_init(struct ieee80211_local *local,
 	 * Note that we never change this, so if link ID 0 isn't used in an
 	 * MLD connection, we get a separate allocation for it.
 	 */
-	sdata->vif.link_conf[0] = &sdata->vif.bss_conf;
-	sdata->link[0] = &sdata->deflink;
-	sdata->deflink.sdata = sdata;
+	ieee80211_link_init(sdata, 0, &sdata->deflink, &sdata->vif.bss_conf);
 }
 
 int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
@@ -1678,12 +1697,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 	skb_queue_head_init(&sdata->status_queue);
 	INIT_WORK(&sdata->work, ieee80211_iface_work);
 	INIT_WORK(&sdata->recalc_smps, ieee80211_recalc_smps_work);
-	INIT_WORK(&sdata->deflink.csa_finalize_work,
-		  ieee80211_csa_finalize_work);
-	INIT_WORK(&sdata->deflink.color_change_finalize_work,
-		  ieee80211_color_change_finalize_work);
-	INIT_LIST_HEAD(&sdata->deflink.assigned_chanctx_list);
-	INIT_LIST_HEAD(&sdata->deflink.reserved_chanctx_list);
 
 	switch (type) {
 	case NL80211_IFTYPE_P2P_GO:
@@ -2100,8 +2113,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 
 	INIT_LIST_HEAD(&sdata->key_list);
 
-	INIT_DELAYED_WORK(&sdata->deflink.dfs_cac_timer_work,
-			  ieee80211_dfs_cac_timer_work);
 	INIT_DELAYED_WORK(&sdata->dec_tailroom_needed_wk,
 			  ieee80211_delayed_tailroom_dec);
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 10/15] mac80211: add link_id to vht.c code for MLO
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (8 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 09/15] mac80211: refactor some link setup code Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 11/15] mac80211: add link_id to eht.c " Johannes Berg
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Update the code in vht.c and add the link_id parameter where
necessary.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 .../net/wireless/intel/iwlwifi/mvm/mac80211.c |   2 +-
 include/net/mac80211.h                        |   3 +-
 net/mac80211/cfg.c                            |   5 +-
 net/mac80211/ibss.c                           |   2 +-
 net/mac80211/ieee80211_i.h                    |  18 +--
 net/mac80211/iface.c                          |   6 +-
 net/mac80211/mesh_plink.c                     |   2 +-
 net/mac80211/mlme.c                           |   6 +-
 net/mac80211/rate.c                           |   2 +-
 net/mac80211/rx.c                             |   2 +-
 net/mac80211/tdls.c                           |   2 +-
 net/mac80211/vht.c                            | 122 +++++++++---------
 12 files changed, 92 insertions(+), 80 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 5d3cedc146be..2539dc5aaa3f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -1776,7 +1776,7 @@ static void iwl_mvm_mu_mimo_iface_iterator(void *_data, u8 *mac,
 		 * the data received from firmware as if it came from the
 		 * action frame, so no conversion is needed.
 		 */
-		ieee80211_update_mu_groups(vif,
+		ieee80211_update_mu_groups(vif, 0,
 					   (u8 *)&notif->membership_status,
 					   (u8 *)&notif->user_position);
 	}
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 66a18dc4462f..a3621900fbe4 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6548,6 +6548,7 @@ ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
  * ieee80211_update_mu_groups - set the VHT MU-MIMO groud data
  *
  * @vif: the specified virtual interface
+ * @link_id: the link ID for MLO, otherwise 0
  * @membership: 64 bits array - a bit is set if station is member of the group
  * @position: 2 bits per group id indicating the position in the group
  *
@@ -6556,7 +6557,7 @@ ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
  * matching GroupId management frame.
  * Calls to this function need to be serialized with RX path.
  */
-void ieee80211_update_mu_groups(struct ieee80211_vif *vif,
+void ieee80211_update_mu_groups(struct ieee80211_vif *vif, unsigned int link_id,
 				const u8 *membership, const u8 *position);
 
 void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e76565cb6292..27eb281f53b6 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1767,7 +1767,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 	/* VHT can override some HT caps such as the A-MSDU max length */
 	if (params->vht_capa)
 		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-						    params->vht_capa, sta);
+						    params->vht_capa, sta, 0);
 
 	if (params->he_capa)
 		ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
@@ -1788,7 +1788,8 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 		/* returned value is only needed for rc update, but the
 		 * rc isn't initialized here yet, so ignore it
 		 */
-		__ieee80211_vht_handle_opmode(sdata, sta, params->opmode_notif,
+		__ieee80211_vht_handle_opmode(sdata, sta, 0,
+					      params->opmode_notif,
 					      sband->band);
 	}
 
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 2ca75f2d3023..87815a3624f3 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1068,7 +1068,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
 						   &chandef);
 			memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie));
 			ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-							    &cap_ie, sta);
+							    &cap_ie, sta, 0);
 			if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap)))
 				rates_updated |= true;
 		}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 92ed1e3c2980..5be96b0bbd96 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2121,29 +2121,31 @@ void
 ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 				    struct ieee80211_supported_band *sband,
 				    const struct ieee80211_vht_cap *vht_cap_ie,
-				    struct sta_info *sta);
+				    struct sta_info *sta, unsigned int link_id);
 enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta,
 							unsigned int link_id);
 enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta,
 							 unsigned int link_id);
-void ieee80211_sta_set_rx_nss(struct sta_info *sta);
+void ieee80211_sta_set_rx_nss(struct sta_info *sta, unsigned int link_id);
 enum ieee80211_sta_rx_bandwidth
 ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width);
-enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta);
+enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta,
+						  unsigned int link_id);
 void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
+				 unsigned int link_id,
 				 struct ieee80211_mgmt *mgmt);
 u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
-                                  struct sta_info *sta, u8 opmode,
-				  enum nl80211_band band);
+				  struct sta_info *sta, unsigned int link_id,
+				  u8 opmode, enum nl80211_band band);
 void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
-				 struct sta_info *sta, u8 opmode,
-				 enum nl80211_band band);
+				 struct sta_info *sta, unsigned int link_id,
+				 u8 opmode, enum nl80211_band band);
 void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
 				      struct ieee80211_sta_vht_cap *vht_cap);
 void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
 				     u16 vht_mask[NL80211_VHT_NSS_MAX]);
 enum nl80211_chan_width
-ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta);
+ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta, unsigned int link_id);
 
 /* HE */
 void
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index fa684d76a169..c5be60ee12d8 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1496,14 +1496,14 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
 			sta = sta_info_get_bss(sdata, mgmt->sa);
 
 			if (sta)
-				ieee80211_vht_handle_opmode(sdata, sta, opmode,
-							    band);
+				ieee80211_vht_handle_opmode(sdata, sta, 0,
+							    opmode, band);
 
 			mutex_unlock(&local->sta_mtx);
 			break;
 		}
 		case WLAN_VHT_ACTION_GROUPID_MGMT:
-			ieee80211_process_mu_groups(sdata, mgmt);
+			ieee80211_process_mu_groups(sdata, 0, mgmt);
 			break;
 		default:
 			WARN_ON(1);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index a6cb1db50f1d..fb7e8a9600ca 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -442,7 +442,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 		changed |= IEEE80211_RC_BW_CHANGED;
 
 	ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-					    elems->vht_cap_elem, sta);
+					    elems->vht_cap_elem, sta, 0);
 
 	ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,
 					  elems->he_cap_len,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ca9e0d83e2a4..643ef0ae786e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3570,7 +3570,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 
 	if (elems->vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
 		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-						    elems->vht_cap_elem, sta);
+						    elems->vht_cap_elem,
+						    sta, 0);
 
 	if (elems->he_operation && !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) &&
 	    elems->he_cap) {
@@ -4377,7 +4378,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 	}
 
 	if (sta && elems->opmode_notif)
-		ieee80211_vht_handle_opmode(sdata, sta, *elems->opmode_notif,
+		ieee80211_vht_handle_opmode(sdata, sta, 0,
+					    *elems->opmode_notif,
 					    rx_status->band);
 	mutex_unlock(&local->sta_mtx);
 
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index b268088585eb..402e898b75c3 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -37,7 +37,7 @@ void rate_control_rate_init(struct sta_info *sta)
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_chanctx_conf *chanctx_conf;
 
-	ieee80211_sta_set_rx_nss(sta);
+	ieee80211_sta_set_rx_nss(sta, 0);
 
 	if (!ref)
 		return;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 1774d0f9feaa..e6b16ebbdb48 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3403,7 +3403,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 			rx->sta->sta.deflink.bandwidth = new_bw;
 			sband = rx->local->hw.wiphy->bands[status->band];
 			sta_opmode.bw =
-				ieee80211_sta_rx_bw_to_chan_width(rx->sta);
+				ieee80211_sta_rx_bw_to_chan_width(rx->sta, 0);
 			sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED;
 
 			rate_control_rate_update(local, sband, rx->sta, 0,
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 86a13ef31ef1..4fc120c64022 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -308,7 +308,7 @@ ieee80211_tdls_chandef_vht_upgrade(struct ieee80211_sub_if_data *sdata,
 	/* IEEE802.11ac-2013 Table E-4 */
 	u16 centers_80mhz[] = { 5210, 5290, 5530, 5610, 5690, 5775 };
 	struct cfg80211_chan_def uc = sta->tdls_chandef;
-	enum nl80211_chan_width max_width = ieee80211_sta_cap_chan_bw(sta);
+	enum nl80211_chan_width max_width = ieee80211_sta_cap_chan_bw(sta, 0);
 	int i;
 
 	/* only support upgrading non-narrow channels up to 80Mhz */
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 27d260be9123..acfe1459535f 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -116,16 +116,16 @@ void
 ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 				    struct ieee80211_supported_band *sband,
 				    const struct ieee80211_vht_cap *vht_cap_ie,
-				    struct sta_info *sta)
+				    struct sta_info *sta, unsigned int link_id)
 {
-	struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.deflink.vht_cap;
+	struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.link[link_id]->vht_cap;
 	struct ieee80211_sta_vht_cap own_cap;
 	u32 cap_info, i;
 	bool have_80mhz;
 
 	memset(vht_cap, 0, sizeof(*vht_cap));
 
-	if (!sta->sta.deflink.ht_cap.ht_supported)
+	if (!sta->sta.link[link_id]->ht_cap.ht_supported)
 		return;
 
 	if (!vht_cap_ie || !sband->vht_cap.vht_supported)
@@ -295,10 +295,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 	switch (vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
 	case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
 	case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
-		sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
+		sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
 		break;
 	default:
-		sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
+		sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
 
 		if (!(vht_cap->vht_mcs.tx_highest &
 				cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE)))
@@ -310,10 +310,11 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
 		 * above) between 160 and 80+80 yet.
 		 */
 		if (cap_info & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK)
-			sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
+			sta->link[link_id]->cur_max_bandwidth =
+				IEEE80211_STA_RX_BW_160;
 	}
 
-	sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta, 0);
+	sta->sta.link[link_id]->bandwidth = ieee80211_sta_cur_vht_bw(sta, link_id);
 
 	switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) {
 	case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
@@ -391,16 +392,17 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta,
 	return IEEE80211_STA_RX_BW_80;
 }
 
-enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta)
+enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta,
+						  unsigned int link_id)
 {
-	struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.deflink.vht_cap;
+	struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.link[link_id]->vht_cap;
 	u32 cap_width;
 
 	if (!vht_cap->vht_supported) {
-		if (!sta->sta.deflink.ht_cap.ht_supported)
+		if (!sta->sta.link[link_id]->ht_cap.ht_supported)
 			return NL80211_CHAN_WIDTH_20_NOHT;
 
-		return sta->sta.deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
+		return sta->sta.link[link_id]->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
 				NL80211_CHAN_WIDTH_40 : NL80211_CHAN_WIDTH_20;
 	}
 
@@ -415,15 +417,17 @@ enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct sta_info *sta)
 }
 
 enum nl80211_chan_width
-ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta)
+ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta, unsigned int link_id)
 {
-	enum ieee80211_sta_rx_bandwidth cur_bw = sta->sta.deflink.bandwidth;
-	struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.deflink.vht_cap;
+	enum ieee80211_sta_rx_bandwidth cur_bw =
+		sta->sta.link[link_id]->bandwidth;
+	struct ieee80211_sta_vht_cap *vht_cap =
+		&sta->sta.link[link_id]->vht_cap;
 	u32 cap_width;
 
 	switch (cur_bw) {
 	case IEEE80211_STA_RX_BW_20:
-		if (!sta->sta.deflink.ht_cap.ht_supported)
+		if (!sta->sta.link[link_id]->ht_cap.ht_supported)
 			return NL80211_CHAN_WIDTH_20_NOHT;
 		else
 			return NL80211_CHAN_WIDTH_20;
@@ -497,18 +501,18 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta,
 	return bw;
 }
 
-void ieee80211_sta_set_rx_nss(struct sta_info *sta)
+void ieee80211_sta_set_rx_nss(struct sta_info *sta, unsigned int link_id)
 {
 	u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, eht_rx_nss = 0, rx_nss;
 	bool support_160;
 
 	/* if we received a notification already don't overwrite it */
-	if (sta->sta.deflink.rx_nss)
+	if (sta->sta.link[link_id]->rx_nss)
 		return;
 
-	if (sta->sta.deflink.eht_cap.has_eht) {
+	if (sta->sta.link[link_id]->eht_cap.has_eht) {
 		int i;
-		const u8 *rx_nss_mcs = (void *)&sta->sta.deflink.eht_cap.eht_mcs_nss_supp;
+		const u8 *rx_nss_mcs = (void *)&sta->sta.link[link_id]->eht_cap.eht_mcs_nss_supp;
 
 		/* get the max nss for EHT over all possible bandwidths and mcs */
 		for (i = 0; i < sizeof(struct ieee80211_eht_mcs_nss_supp); i++)
@@ -517,10 +521,10 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
 						       IEEE80211_EHT_MCS_NSS_RX));
 	}
 
-	if (sta->sta.deflink.he_cap.has_he) {
+	if (sta->sta.link[link_id]->he_cap.has_he) {
 		int i;
 		u8 rx_mcs_80 = 0, rx_mcs_160 = 0;
-		const struct ieee80211_sta_he_cap *he_cap = &sta->sta.deflink.he_cap;
+		const struct ieee80211_sta_he_cap *he_cap = &sta->sta.link[link_id]->he_cap;
 		u16 mcs_160_map =
 			le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
 		u16 mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
@@ -551,23 +555,23 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
 			he_rx_nss = rx_mcs_80;
 	}
 
-	if (sta->sta.deflink.ht_cap.ht_supported) {
-		if (sta->sta.deflink.ht_cap.mcs.rx_mask[0])
+	if (sta->sta.link[link_id]->ht_cap.ht_supported) {
+		if (sta->sta.link[link_id]->ht_cap.mcs.rx_mask[0])
 			ht_rx_nss++;
-		if (sta->sta.deflink.ht_cap.mcs.rx_mask[1])
+		if (sta->sta.link[link_id]->ht_cap.mcs.rx_mask[1])
 			ht_rx_nss++;
-		if (sta->sta.deflink.ht_cap.mcs.rx_mask[2])
+		if (sta->sta.link[link_id]->ht_cap.mcs.rx_mask[2])
 			ht_rx_nss++;
-		if (sta->sta.deflink.ht_cap.mcs.rx_mask[3])
+		if (sta->sta.link[link_id]->ht_cap.mcs.rx_mask[3])
 			ht_rx_nss++;
 		/* FIXME: consider rx_highest? */
 	}
 
-	if (sta->sta.deflink.vht_cap.vht_supported) {
+	if (sta->sta.link[link_id]->vht_cap.vht_supported) {
 		int i;
 		u16 rx_mcs_map;
 
-		rx_mcs_map = le16_to_cpu(sta->sta.deflink.vht_cap.vht_mcs.rx_mcs_map);
+		rx_mcs_map = le16_to_cpu(sta->sta.link[link_id]->vht_cap.vht_mcs.rx_mcs_map);
 
 		for (i = 7; i >= 0; i--) {
 			u8 mcs = (rx_mcs_map >> (2 * i)) & 3;
@@ -583,12 +587,12 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
 	rx_nss = max(vht_rx_nss, ht_rx_nss);
 	rx_nss = max(he_rx_nss, rx_nss);
 	rx_nss = max(eht_rx_nss, rx_nss);
-	sta->sta.deflink.rx_nss = max_t(u8, 1, rx_nss);
+	sta->sta.link[link_id]->rx_nss = max_t(u8, 1, rx_nss);
 }
 
 u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
-				  struct sta_info *sta, u8 opmode,
-				  enum nl80211_band band)
+				  struct sta_info *sta, unsigned int link_id,
+				  u8 opmode, enum nl80211_band band)
 {
 	enum ieee80211_sta_rx_bandwidth new_bw;
 	struct sta_opmode_info sta_opmode = {};
@@ -603,8 +607,8 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 	nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;
 	nss += 1;
 
-	if (sta->sta.deflink.rx_nss != nss) {
-		sta->sta.deflink.rx_nss = nss;
+	if (sta->sta.link[link_id]->rx_nss != nss) {
+		sta->sta.link[link_id]->rx_nss = nss;
 		sta_opmode.rx_nss = nss;
 		changed |= IEEE80211_RC_NSS_CHANGED;
 		sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED;
@@ -613,28 +617,28 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 	switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
 	case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
 		/* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
-		sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
+		sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
 		break;
 	case IEEE80211_OPMODE_NOTIF_CHANWIDTH_40MHZ:
 		/* ignore IEEE80211_OPMODE_NOTIF_BW_160_80P80 must not be set */
-		sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_40;
+		sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_40;
 		break;
 	case IEEE80211_OPMODE_NOTIF_CHANWIDTH_80MHZ:
 		if (opmode & IEEE80211_OPMODE_NOTIF_BW_160_80P80)
-			sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
+			sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
 		else
-			sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
+			sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_80;
 		break;
 	case IEEE80211_OPMODE_NOTIF_CHANWIDTH_160MHZ:
 		/* legacy only, no longer used by newer spec */
-		sta->deflink.cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
+		sta->link[link_id]->cur_max_bandwidth = IEEE80211_STA_RX_BW_160;
 		break;
 	}
 
-	new_bw = ieee80211_sta_cur_vht_bw(sta, 0);
-	if (new_bw != sta->sta.deflink.bandwidth) {
-		sta->sta.deflink.bandwidth = new_bw;
-		sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta);
+	new_bw = ieee80211_sta_cur_vht_bw(sta, link_id);
+	if (new_bw != sta->sta.link[link_id]->bandwidth) {
+		sta->sta.link[link_id]->bandwidth = new_bw;
+		sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta, link_id);
 		changed |= IEEE80211_RC_BW_CHANGED;
 		sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED;
 	}
@@ -647,54 +651,56 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 }
 
 void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata,
+				 unsigned int link_id,
 				 struct ieee80211_mgmt *mgmt)
 {
-	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
+	struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
 
-	if (!sdata->vif.bss_conf.mu_mimo_owner)
+	if (!link_conf->mu_mimo_owner)
 		return;
 
 	if (!memcmp(mgmt->u.action.u.vht_group_notif.position,
-		    bss_conf->mu_group.position, WLAN_USER_POSITION_LEN) &&
+		    link_conf->mu_group.position, WLAN_USER_POSITION_LEN) &&
 	    !memcmp(mgmt->u.action.u.vht_group_notif.membership,
-		    bss_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN))
+		    link_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN))
 		return;
 
-	memcpy(bss_conf->mu_group.membership,
+	memcpy(link_conf->mu_group.membership,
 	       mgmt->u.action.u.vht_group_notif.membership,
 	       WLAN_MEMBERSHIP_LEN);
-	memcpy(bss_conf->mu_group.position,
+	memcpy(link_conf->mu_group.position,
 	       mgmt->u.action.u.vht_group_notif.position,
 	       WLAN_USER_POSITION_LEN);
 
-	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_MU_GROUPS);
+	ieee80211_link_info_change_notify(sdata, link_id, BSS_CHANGED_MU_GROUPS);
 }
 
-void ieee80211_update_mu_groups(struct ieee80211_vif *vif,
+void ieee80211_update_mu_groups(struct ieee80211_vif *vif, unsigned int link_id,
 				const u8 *membership, const u8 *position)
 {
-	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	struct ieee80211_bss_conf *link_conf = vif->link_conf[link_id];
 
-	if (WARN_ON_ONCE(!vif->bss_conf.mu_mimo_owner))
+	if (WARN_ON_ONCE(!link_conf->mu_mimo_owner))
 		return;
 
-	memcpy(bss_conf->mu_group.membership, membership, WLAN_MEMBERSHIP_LEN);
-	memcpy(bss_conf->mu_group.position, position, WLAN_USER_POSITION_LEN);
+	memcpy(link_conf->mu_group.membership, membership, WLAN_MEMBERSHIP_LEN);
+	memcpy(link_conf->mu_group.position, position, WLAN_USER_POSITION_LEN);
 }
 EXPORT_SYMBOL_GPL(ieee80211_update_mu_groups);
 
 void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
-				 struct sta_info *sta, u8 opmode,
-				 enum nl80211_band band)
+				 struct sta_info *sta, unsigned int link_id,
+				 u8 opmode, enum nl80211_band band)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
 
-	u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
+	u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, link_id,
+						    opmode, band);
 
 	if (changed > 0) {
 		ieee80211_recalc_min_chandef(sdata);
-		rate_control_rate_update(local, sband, sta, 0, changed);
+		rate_control_rate_update(local, sband, sta, link_id, changed);
 	}
 }
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 11/15] mac80211: add link_id to eht.c code for MLO
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (9 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 10/15] mac80211: add link_id to vht.c code for MLO Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 12/15] mac80211: HT: make ieee80211_ht_cap_ie_to_sta_ht_cap() MLO-aware Johannes Berg
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Update the code in eht.c and add the link_id parameter where
necessary.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c         |  2 +-
 net/mac80211/eht.c         | 12 ++++++++----
 net/mac80211/ieee80211_i.h |  3 ++-
 net/mac80211/mlme.c        |  2 +-
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 27eb281f53b6..0afff3b0aeee 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1782,7 +1782,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 						    params->he_capa_len,
 						    params->eht_capa,
 						    params->eht_capa_len,
-						    sta);
+						    sta, 0);
 
 	if (params->opmode_notif_used) {
 		/* returned value is only needed for rc update, but the
diff --git a/net/mac80211/eht.c b/net/mac80211/eht.c
index 2d9c6e845ce4..de762a803c38 100644
--- a/net/mac80211/eht.c
+++ b/net/mac80211/eht.c
@@ -12,9 +12,11 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
 				    struct ieee80211_supported_band *sband,
 				    const u8 *he_cap_ie, u8 he_cap_len,
 				    const struct ieee80211_eht_cap_elem *eht_cap_ie_elem,
-				    u8 eht_cap_len, struct sta_info *sta)
+				    u8 eht_cap_len, struct sta_info *sta,
+				    unsigned int link_id)
 {
-	struct ieee80211_sta_eht_cap *eht_cap = &sta->sta.deflink.eht_cap;
+	struct ieee80211_sta_eht_cap *eht_cap =
+		&sta->sta.link[link_id]->eht_cap;
 	struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie;
 	u8 eht_ppe_size = 0;
 	u8 mcs_nss_size;
@@ -71,6 +73,8 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
 
 	eht_cap->has_eht = true;
 
-	sta->deflink.cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta, 0);
-	sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta, 0);
+	sta->link[link_id]->cur_max_bandwidth =
+		ieee80211_sta_cap_rx_bw(sta, link_id);
+	sta->sta.link[link_id]->bandwidth =
+		ieee80211_sta_cur_vht_bw(sta, link_id);
 }
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5be96b0bbd96..c59dc8f6126b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2577,5 +2577,6 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
 				    struct ieee80211_supported_band *sband,
 				    const u8 *he_cap_ie, u8 he_cap_len,
 				    const struct ieee80211_eht_cap_elem *eht_cap_ie_elem,
-				    u8 eht_cap_len, struct sta_info *sta);
+				    u8 eht_cap_len, struct sta_info *sta,
+				    unsigned int link_id);
 #endif /* IEEE80211_I_H */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 643ef0ae786e..459780169e23 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3599,7 +3599,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 							    elems->he_cap_len,
 							    elems->eht_cap,
 							    elems->eht_cap_len,
-							    sta);
+							    sta, 0);
 
 			bss_conf->eht_support = sta->sta.deflink.eht_cap.has_eht;
 		} else {
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 12/15] mac80211: HT: make ieee80211_ht_cap_ie_to_sta_ht_cap() MLO-aware
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (10 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 11/15] mac80211: add link_id to eht.c " Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 13/15] mac80211: make some SMPS code MLD-aware Johannes Berg
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Update ieee80211_ht_cap_ie_to_sta_ht_cap() to handle per-link
data.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c         |  2 +-
 net/mac80211/ht.c          | 13 +++++++------
 net/mac80211/ibss.c        |  2 +-
 net/mac80211/ieee80211_i.h |  2 +-
 net/mac80211/mesh_plink.c  |  2 +-
 net/mac80211/mlme.c        |  2 +-
 6 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0afff3b0aeee..cc332b31d219 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1762,7 +1762,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 
 	if (params->ht_capa)
 		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
-						  params->ht_capa, sta);
+						  params->ht_capa, sta, 0);
 
 	/* VHT can override some HT caps such as the A-MSDU max length */
 	if (params->vht_capa)
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index ac94dd69c0a2..22677df83ed8 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -138,7 +138,7 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
 bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 				       struct ieee80211_supported_band *sband,
 				       const struct ieee80211_ht_cap *ht_cap_ie,
-				       struct sta_info *sta)
+				       struct sta_info *sta, unsigned int link_id)
 {
 	struct ieee80211_sta_ht_cap ht_cap, own_cap;
 	u8 ampdu_info, tx_mcs_set_cap;
@@ -243,11 +243,12 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 		sta->sta.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_HT_3839;
 
  apply:
-	changed = memcmp(&sta->sta.deflink.ht_cap, &ht_cap, sizeof(ht_cap));
+	changed = memcmp(&sta->sta.link[link_id]->ht_cap,
+			 &ht_cap, sizeof(ht_cap));
 
-	memcpy(&sta->sta.deflink.ht_cap, &ht_cap, sizeof(ht_cap));
+	memcpy(&sta->sta.link[link_id]->ht_cap, &ht_cap, sizeof(ht_cap));
 
-	switch (sdata->vif.bss_conf.chandef.width) {
+	switch (sdata->vif.link_conf[link_id]->chandef.width) {
 	default:
 		WARN_ON_ONCE(1);
 		fallthrough;
@@ -264,9 +265,9 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 		break;
 	}
 
-	sta->sta.deflink.bandwidth = bw;
+	sta->sta.link[link_id]->bandwidth = bw;
 
-	sta->deflink.cur_max_bandwidth =
+	sta->link[link_id]->cur_max_bandwidth =
 		ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
 				IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
 
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 87815a3624f3..09c11c067cbf 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1051,7 +1051,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata,
 		memcpy(&htcap_ie, elems->ht_cap_elem, sizeof(htcap_ie));
 		rates_updated |= ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
 								   &htcap_ie,
-								   sta);
+								   sta, 0);
 
 		if (elems->vht_operation && elems->vht_cap_elem &&
 		    sdata->u.ibss.chandef.width != NL80211_CHAN_WIDTH_20 &&
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c59dc8f6126b..e75496a99299 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2065,7 +2065,7 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
 bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
 				       struct ieee80211_supported_band *sband,
 				       const struct ieee80211_ht_cap *ht_cap_ie,
-				       struct sta_info *sta);
+				       struct sta_info *sta, unsigned int link_id);
 void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
 			  const u8 *da, u16 tid,
 			  u16 initiator, u16 reason_code);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index fb7e8a9600ca..b64614cd314d 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -438,7 +438,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 	sta->sta.deflink.supp_rates[sband->band] = rates;
 
 	if (ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
-					      elems->ht_cap_elem, sta))
+					      elems->ht_cap_elem, sta, 0))
 		changed |= IEEE80211_RC_BW_CHANGED;
 
 	ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 459780169e23..30423b2d4eee 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3566,7 +3566,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 	/* Set up internal HT/VHT capabilities */
 	if (elems->ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
 		ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
-						  elems->ht_cap_elem, sta);
+						  elems->ht_cap_elem, sta, 0);
 
 	if (elems->vht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
 		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 13/15] mac80211: make some SMPS code MLD-aware
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (11 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 12/15] mac80211: HT: make ieee80211_ht_cap_ie_to_sta_ht_cap() MLO-aware Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 14/15] mac80211: make ieee80211_he_cap_ie_to_sta_he_cap() MLO-aware Johannes Berg
  2022-06-01  7:39 ` [PATCH 15/15] mac80211: correct link config data in tracing Johannes Berg
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Start making some SMPS related code MLD-aware. This isn't
really done yet, but again cuts down our 'deflink' reliance.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/intel/iwlwifi/dvm/lib.c  |  4 +--
 .../net/wireless/intel/iwlwifi/mvm/utils.c    |  2 +-
 drivers/net/wireless/realtek/rtw88/main.c     |  4 +--
 include/net/mac80211.h                        |  3 +-
 net/mac80211/cfg.c                            | 19 ++++++++----
 net/mac80211/debugfs_netdev.c                 |  2 +-
 net/mac80211/ht.c                             | 29 ++++++++++---------
 net/mac80211/ieee80211_i.h                    |  4 ++-
 net/mac80211/iface.c                          |  2 +-
 net/mac80211/mlme.c                           |  2 +-
 net/mac80211/util.c                           |  5 ++--
 11 files changed, 45 insertions(+), 31 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
index 40d790b36d85..1dc974e2c511 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/lib.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /******************************************************************************
  *
- * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2008 - 2014, 2022 Intel Corporation. All rights reserved.
  *****************************************************************************/
 #include <linux/etherdevice.h>
 #include <linux/kernel.h>
@@ -441,7 +441,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
 		priv->current_ht_config.smps = smps_request;
 		for_each_context(priv, ctx) {
 			if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
-				ieee80211_request_smps(ctx->vif, smps_request);
+				ieee80211_request_smps(ctx->vif, 0, smps_request);
 		}
 	}
 
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index 3ee5ea3484be..14b2de65bd84 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -304,7 +304,7 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 			smps_mode = IEEE80211_SMPS_DYNAMIC;
 	}
 
-	ieee80211_request_smps(vif, smps_mode);
+	ieee80211_request_smps(vif, 0, smps_mode);
 }
 
 static bool iwl_wait_stats_complete(struct iwl_notif_wait_data *notif_wait,
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index b151af13e310..a5d541b71ab9 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -1596,9 +1596,9 @@ static void rtw_vif_smps_iter(void *data, u8 *mac,
 		return;
 
 	if (rtwdev->hal.txrx_1ss)
-		ieee80211_request_smps(vif, IEEE80211_SMPS_STATIC);
+		ieee80211_request_smps(vif, 0, IEEE80211_SMPS_STATIC);
 	else
-		ieee80211_request_smps(vif, IEEE80211_SMPS_OFF);
+		ieee80211_request_smps(vif, 0, IEEE80211_SMPS_OFF);
 }
 
 void rtw_set_txrx_1ss(struct rtw_dev *rtwdev, bool txrx_1ss)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a3621900fbe4..e7e91b283cab 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6210,13 +6210,14 @@ void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif,
 /**
  * ieee80211_request_smps - request SM PS transition
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @link_id: link ID for MLO, or 0
  * @smps_mode: new SM PS mode
  *
  * This allows the driver to request an SM PS transition in managed
  * mode. This is useful when the driver has more information than
  * the stack about possible interference, for example by bluetooth.
  */
-void ieee80211_request_smps(struct ieee80211_vif *vif,
+void ieee80211_request_smps(struct ieee80211_vif *vif, unsigned int link_id,
 			    enum ieee80211_smps_mode smps_mode);
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index cc332b31d219..cf63542d40fa 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2917,6 +2917,7 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy,
 #endif
 
 int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
+				 unsigned int link_id,
 				 enum ieee80211_smps_mode smps_mode)
 {
 	const u8 *ap;
@@ -2930,8 +2931,8 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
 	if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION))
 		return -EINVAL;
 
-	old_req = sdata->deflink.u.mgd.req_smps;
-	sdata->deflink.u.mgd.req_smps = smps_mode;
+	old_req = sdata->link[link_id]->u.mgd.req_smps;
+	sdata->link[link_id]->u.mgd.req_smps = smps_mode;
 
 	if (old_req == smps_mode &&
 	    smps_mode != IEEE80211_SMPS_AUTOMATIC)
@@ -2943,10 +2944,10 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
 	 * the new value until we associate.
 	 */
 	if (!sdata->u.mgd.associated ||
-	    sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
+	    sdata->vif.link_conf[link_id]->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
 		return 0;
 
-	ap = sdata->deflink.u.mgd.bssid;
+	ap = sdata->link[link_id]->u.mgd.bssid;
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
@@ -2970,7 +2971,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
 	err = ieee80211_send_smps_action(sdata, smps_mode,
 					 ap, ap);
 	if (err)
-		sdata->deflink.u.mgd.req_smps = old_req;
+		sdata->link[link_id]->u.mgd.req_smps = old_req;
 	else if (smps_mode != IEEE80211_SMPS_OFF && tdls_peer_found)
 		ieee80211_teardown_tdls_peers(sdata);
 
@@ -2982,6 +2983,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+	unsigned int link_id;
 
 	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 		return -EOPNOTSUPP;
@@ -2998,7 +3000,12 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 
 	/* no change, but if automatic follow powersave */
 	sdata_lock(sdata);
-	__ieee80211_request_smps_mgd(sdata, sdata->deflink.u.mgd.req_smps);
+	for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
+		if (!sdata->link[link_id])
+			continue;
+		__ieee80211_request_smps_mgd(sdata, link_id,
+					     sdata->link[link_id]->u.mgd.req_smps);
+	}
 	sdata_unlock(sdata);
 
 	if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index bd398b631763..dfb194e15018 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -256,7 +256,7 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
 		return -EOPNOTSUPP;
 
 	sdata_lock(sdata);
-	err = __ieee80211_request_smps_mgd(sdata, smps_mode);
+	err = __ieee80211_request_smps_mgd(sdata, 0, smps_mode);
 	sdata_unlock(sdata);
 
 	return err;
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 22677df83ed8..111828b559a0 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -542,30 +542,33 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
 
 void ieee80211_request_smps_mgd_work(struct work_struct *work)
 {
-	struct ieee80211_sub_if_data *sdata =
-		container_of(work, struct ieee80211_sub_if_data,
-			     deflink.u.mgd.request_smps_work);
-
-	sdata_lock(sdata);
-	__ieee80211_request_smps_mgd(sdata,
-				     sdata->deflink.u.mgd.driver_smps_mode);
-	sdata_unlock(sdata);
+	struct ieee80211_link_data *link =
+		container_of(work, struct ieee80211_link_data,
+			     u.mgd.request_smps_work);
+
+	sdata_lock(link->sdata);
+	__ieee80211_request_smps_mgd(link->sdata, link->link_id,
+				     link->u.mgd.driver_smps_mode);
+	sdata_unlock(link->sdata);
 }
 
-void ieee80211_request_smps(struct ieee80211_vif *vif,
+void ieee80211_request_smps(struct ieee80211_vif *vif, unsigned int link_id,
 			    enum ieee80211_smps_mode smps_mode)
 {
 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	struct ieee80211_link_data *link = sdata->link[link_id];
 
 	if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION))
 		return;
 
-	if (sdata->deflink.u.mgd.driver_smps_mode == smps_mode)
+	if (WARN_ON(!link))
 		return;
 
-	sdata->deflink.u.mgd.driver_smps_mode = smps_mode;
-	ieee80211_queue_work(&sdata->local->hw,
-			     &sdata->deflink.u.mgd.request_smps_work);
+	if (link->u.mgd.driver_smps_mode == smps_mode)
+		return;
+
+	link->u.mgd.driver_smps_mode = smps_mode;
+	ieee80211_queue_work(&sdata->local->hw, &link->u.mgd.request_smps_work);
 }
 /* this might change ... don't want non-open drivers using it */
 EXPORT_SYMBOL_GPL(ieee80211_request_smps);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e75496a99299..0948d074c4b9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2422,8 +2422,10 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
 			    struct ieee802_11_elems *elems,
 			    enum nl80211_band band, u32 *basic_rates);
 int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
+				 unsigned int link_id,
 				 enum ieee80211_smps_mode smps_mode);
-void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
+void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata,
+			   unsigned int link_id);
 void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
 
 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index c5be60ee12d8..ea75d5d5cb6a 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1657,7 +1657,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
 	struct ieee80211_sub_if_data *sdata =
 		container_of(work, struct ieee80211_sub_if_data, recalc_smps);
 
-	ieee80211_recalc_smps(sdata);
+	ieee80211_recalc_smps(sdata, 0);
 }
 
 /*
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 30423b2d4eee..cdbf7a5dc2ba 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2337,7 +2337,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 	ieee80211_recalc_ps(local);
 	mutex_unlock(&local->iflist_mtx);
 
-	ieee80211_recalc_smps(sdata);
+	ieee80211_recalc_smps(sdata, 0);
 	ieee80211_recalc_ps_vif(sdata);
 
 	netif_carrier_on(sdata->dev);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 4ec96170a679..ecda655e7481 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2803,7 +2803,8 @@ void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
 }
 EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
 
-void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)
+void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata,
+			   unsigned int link_id)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_chanctx_conf *chanctx_conf;
@@ -2811,7 +2812,7 @@ void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)
 
 	mutex_lock(&local->chanctx_mtx);
 
-	chanctx_conf = rcu_dereference_protected(sdata->vif.bss_conf.chanctx_conf,
+	chanctx_conf = rcu_dereference_protected(sdata->vif.link_conf[link_id]->chanctx_conf,
 						 lockdep_is_held(&local->chanctx_mtx));
 
 	/*
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 14/15] mac80211: make ieee80211_he_cap_ie_to_sta_he_cap() MLO-aware
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (12 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 13/15] mac80211: make some SMPS code MLD-aware Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  2022-06-01  7:39 ` [PATCH 15/15] mac80211: correct link config data in tracing Johannes Berg
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Add the link_id parameter and adjust the code accordingly.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c         |  2 +-
 net/mac80211/he.c          | 16 +++++++++-------
 net/mac80211/ieee80211_i.h |  2 +-
 net/mac80211/mesh_plink.c  |  2 +-
 net/mac80211/mlme.c        |  2 +-
 5 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index cf63542d40fa..bc243716bda0 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1774,7 +1774,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 						  (void *)params->he_capa,
 						  params->he_capa_len,
 						  (void *)params->he_6ghz_capa,
-						  sta);
+						  sta, 0);
 
 	if (params->eht_capa)
 		ieee80211_eht_cap_ie_to_sta_eht_cap(sdata, sband,
diff --git a/net/mac80211/he.c b/net/mac80211/he.c
index 20448dda8c4d..e48e9a021622 100644
--- a/net/mac80211/he.c
+++ b/net/mac80211/he.c
@@ -10,7 +10,7 @@
 
 static void
 ieee80211_update_from_he_6ghz_capa(const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
-				   struct sta_info *sta)
+				   struct sta_info *sta, unsigned int link_id)
 {
 	enum ieee80211_smps_mode smps_mode;
 
@@ -49,7 +49,7 @@ ieee80211_update_from_he_6ghz_capa(const struct ieee80211_he_6ghz_capa *he_6ghz_
 		break;
 	}
 
-	sta->sta.deflink.he_6ghz_capa = *he_6ghz_capa;
+	sta->sta.link[link_id]->he_6ghz_capa = *he_6ghz_capa;
 }
 
 static void ieee80211_he_mcs_disable(__le16 *he_mcs)
@@ -108,9 +108,9 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
 				  struct ieee80211_supported_band *sband,
 				  const u8 *he_cap_ie, u8 he_cap_len,
 				  const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
-				  struct sta_info *sta)
+				  struct sta_info *sta, unsigned int link_id)
 {
-	struct ieee80211_sta_he_cap *he_cap = &sta->sta.deflink.he_cap;
+	struct ieee80211_sta_he_cap *he_cap = &sta->sta.link[link_id]->he_cap;
 	struct ieee80211_sta_he_cap own_he_cap;
 	struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie;
 	u8 he_ppe_size;
@@ -153,11 +153,13 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
 
 	he_cap->has_he = true;
 
-	sta->deflink.cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta, 0);
-	sta->sta.deflink.bandwidth = ieee80211_sta_cur_vht_bw(sta, 0);
+	sta->link[link_id]->cur_max_bandwidth =
+		ieee80211_sta_cap_rx_bw(sta, link_id);
+	sta->sta.link[link_id]->bandwidth =
+		ieee80211_sta_cur_vht_bw(sta, link_id);
 
 	if (sband->band == NL80211_BAND_6GHZ && he_6ghz_capa)
-		ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, sta);
+		ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, sta, link_id);
 
 	ieee80211_he_mcs_intersection(&own_he_cap.he_mcs_nss_supp.rx_mcs_80,
 				      &he_cap->he_mcs_nss_supp.rx_mcs_80,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0948d074c4b9..c3387ffe27f5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2153,7 +2153,7 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata,
 				  struct ieee80211_supported_band *sband,
 				  const u8 *he_cap_ie, u8 he_cap_len,
 				  const struct ieee80211_he_6ghz_capa *he_6ghz_capa,
-				  struct sta_info *sta);
+				  struct sta_info *sta, unsigned int link_id);
 void
 ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif,
 				const struct ieee80211_he_spr *he_spr_ie_elem);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index b64614cd314d..e24bd48bc915 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -447,7 +447,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
 	ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap,
 					  elems->he_cap_len,
 					  elems->he_6ghz_capa,
-					  sta);
+					  sta, 0);
 
 	if (bw != sta->sta.deflink.bandwidth)
 		changed |= IEEE80211_RC_BW_CHANGED;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index cdbf7a5dc2ba..b6ee8da07663 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3579,7 +3579,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 						  elems->he_cap,
 						  elems->he_cap_len,
 						  elems->he_6ghz_capa,
-						  sta);
+						  sta, 0);
 
 		bss_conf->he_support = sta->sta.deflink.he_cap.has_he;
 		if (elems->rsnx && elems->rsnx_len &&
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [PATCH 15/15] mac80211: correct link config data in tracing
  2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
                   ` (13 preceding siblings ...)
  2022-06-01  7:39 ` [PATCH 14/15] mac80211: make ieee80211_he_cap_ie_to_sta_he_cap() MLO-aware Johannes Berg
@ 2022-06-01  7:39 ` Johannes Berg
  14 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01  7:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

We need to no longer use bss_conf here, but the per-link data.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/trace.h | 48 +++++++++++++++++++++++---------------------
 1 file changed, 25 insertions(+), 23 deletions(-)

diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 5c941fe4d70a..4c6c02dd697d 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -481,34 +481,36 @@ TRACE_EVENT(drv_link_info_changed,
 	),
 
 	TP_fast_assign(
+		struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
+
 		LOCAL_ASSIGN;
 		VIF_ASSIGN;
 		__entry->changed = changed;
 		__entry->link_id = link_id;
-		__entry->shortpre = sdata->vif.bss_conf.use_short_preamble;
-		__entry->cts = sdata->vif.bss_conf.use_cts_prot;
-		__entry->shortslot = sdata->vif.bss_conf.use_short_slot;
-		__entry->enable_beacon = sdata->vif.bss_conf.enable_beacon;
-		__entry->dtimper = sdata->vif.bss_conf.dtim_period;
-		__entry->bcnint = sdata->vif.bss_conf.beacon_int;
-		__entry->assoc_cap = sdata->vif.bss_conf.assoc_capability;
-		__entry->sync_tsf = sdata->vif.bss_conf.sync_tsf;
-		__entry->sync_device_ts = sdata->vif.bss_conf.sync_device_ts;
-		__entry->sync_dtim_count = sdata->vif.bss_conf.sync_dtim_count;
-		__entry->basic_rates = sdata->vif.bss_conf.basic_rates;
-		memcpy(__entry->mcast_rate, sdata->vif.bss_conf.mcast_rate,
+		__entry->shortpre = link_conf->use_short_preamble;
+		__entry->cts = link_conf->use_cts_prot;
+		__entry->shortslot = link_conf->use_short_slot;
+		__entry->enable_beacon = link_conf->enable_beacon;
+		__entry->dtimper = link_conf->dtim_period;
+		__entry->bcnint = link_conf->beacon_int;
+		__entry->assoc_cap = link_conf->assoc_capability;
+		__entry->sync_tsf = link_conf->sync_tsf;
+		__entry->sync_device_ts = link_conf->sync_device_ts;
+		__entry->sync_dtim_count = link_conf->sync_dtim_count;
+		__entry->basic_rates = link_conf->basic_rates;
+		memcpy(__entry->mcast_rate, link_conf->mcast_rate,
 		       sizeof(__entry->mcast_rate));
-		__entry->ht_operation_mode = sdata->vif.bss_conf.ht_operation_mode;
-		__entry->cqm_rssi_thold = sdata->vif.bss_conf.cqm_rssi_thold;
-		__entry->cqm_rssi_hyst = sdata->vif.bss_conf.cqm_rssi_hyst;
-		__entry->channel_width = sdata->vif.bss_conf.chandef.width;
-		__entry->channel_cfreq1 = sdata->vif.bss_conf.chandef.center_freq1;
-		__entry->channel_cfreq1_offset = sdata->vif.bss_conf.chandef.freq1_offset;
-		__entry->qos = sdata->vif.bss_conf.qos;
-		__entry->ps = sdata->vif.bss_conf.ps;
-		__entry->hidden_ssid = sdata->vif.bss_conf.hidden_ssid;
-		__entry->txpower = sdata->vif.bss_conf.txpower;
-		__entry->p2p_oppps_ctwindow = sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow;
+		__entry->ht_operation_mode = link_conf->ht_operation_mode;
+		__entry->cqm_rssi_thold = link_conf->cqm_rssi_thold;
+		__entry->cqm_rssi_hyst = link_conf->cqm_rssi_hyst;
+		__entry->channel_width = link_conf->chandef.width;
+		__entry->channel_cfreq1 = link_conf->chandef.center_freq1;
+		__entry->channel_cfreq1_offset = link_conf->chandef.freq1_offset;
+		__entry->qos = link_conf->qos;
+		__entry->ps = link_conf->ps;
+		__entry->hidden_ssid = link_conf->hidden_ssid;
+		__entry->txpower = link_conf->txpower;
+		__entry->p2p_oppps_ctwindow = link_conf->p2p_noa_attr.oppps_ctwindow;
 	),
 
 	TP_printk(
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-06-01  7:39 ` [PATCH 01/15] mac80211: split bss_info_changed method Johannes Berg
@ 2022-06-01 19:31   ` Jeff Johnson
  2022-06-01 19:39     ` Johannes Berg
  2022-10-18  8:47     ` Wen Gong
  1 sibling, 1 reply; 53+ messages in thread
From: Jeff Johnson @ 2022-06-01 19:31 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: Johannes Berg

On 6/1/2022 12:39 AM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
> 
> Split the bss_info_changed method to vif_cfg_changed and
> link_info_changed, with the latter getting a link ID.
> Also change the 'changed' parameter to u64 already, we
> know we need that.

[snip]

> -	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
> -		    vif, changed);
> +	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%llx\n",
> +		    vif, (unsigned long long)changed);

just curious about the typecasting.

https://www.kernel.org/doc/html/latest/core-api/printk-formats.html 
indicates we should always be able to use %lld or %llx for u64 hence no 
typecasting should be needed


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-06-01 19:31   ` Jeff Johnson
@ 2022-06-01 19:39     ` Johannes Berg
  0 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-06-01 19:39 UTC (permalink / raw)
  To: Jeff Johnson, linux-wireless

On Wed, 2022-06-01 at 12:31 -0700, Jeff Johnson wrote:
> On 6/1/2022 12:39 AM, Johannes Berg wrote:
> > From: Johannes Berg <johannes.berg@intel.com>
> > 
> > Split the bss_info_changed method to vif_cfg_changed and
> > link_info_changed, with the latter getting a link ID.
> > Also change the 'changed' parameter to u64 already, we
> > know we need that.
> 
> [snip]
> 
> > -	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
> > -		    vif, changed);
> > +	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%llx\n",
> > +		    vif, (unsigned long long)changed);
> 
> just curious about the typecasting.
> 
> https://www.kernel.org/doc/html/latest/core-api/printk-formats.html 
> indicates we should always be able to use %lld or %llx for u64 hence no 
> typecasting should be needed
> 

Hm. I think you're probably right - I used powerpc 20 years ago and it
had 'unsigned long' for u64, but I guess that changed a LONG time ago...
Yep, commit fe333321e2a71 (Jan 2009). Sorry, old habits die hard. :(

johannes

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-06-01  7:39 ` [PATCH 01/15] mac80211: split bss_info_changed method Johannes Berg
  2022-06-01 19:31   ` Jeff Johnson
@ 2022-10-18  8:47     ` Wen Gong
  1 sibling, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18  8:47 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: Johannes Berg, ath11k, ath12k

On 6/1/2022 3:39 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Split the bss_info_changed method to vif_cfg_changed and
> link_info_changed, with the latter getting a link ID.
> Also change the 'changed' parameter to u64 already, we
> know we need that.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>   
...
> diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> index 0c81ae492df4..6165b90bf0e2 100644
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -199,15 +199,84 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
>   	return ret;
>   }
>   
> +#define BSS_CHANGED_VIF_CFG_FLAGS (BSS_CHANGED_ASSOC |\
> +				   BSS_CHANGED_IDLE |\
> +				   BSS_CHANGED_IBSS |\
> +				   BSS_CHANGED_ARP_FILTER |\
> +				   BSS_CHANGED_SSID)
> +
>   void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
> -				      u32 changed)
> +				      u64 changed)
>   {
>   	struct ieee80211_local *local = sdata->local;
>   
> +	might_sleep();
> +
>   	if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
>   		return;
>   
> -	drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
> +	if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON |
> +				    BSS_CHANGED_BEACON_ENABLED) &&
> +			 sdata->vif.type != NL80211_IFTYPE_AP &&
> +			 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
> +			 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
> +			 sdata->vif.type != NL80211_IFTYPE_OCB))
> +		return;
> +
> +	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
> +			 sdata->vif.type == NL80211_IFTYPE_NAN ||
> +			 (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
> +			  !sdata->vif.bss_conf.mu_mimo_owner &&
> +			  !(changed & BSS_CHANGED_TXPOWER))))
> +		return;
> +
> +	if (!check_sdata_in_driver(sdata))
> +		return;
> +
> +	if (changed & BSS_CHANGED_VIF_CFG_FLAGS) {
> +		trace_drv_vif_cfg_changed(local, sdata, changed);
> +		if (local->ops->vif_cfg_changed)
> +			local->ops->vif_cfg_changed(&local->hw, &sdata->vif, changed);
> +	}
> +
> +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
> +		/* FIXME: should be for each link */
> +		trace_drv_link_info_changed(local, sdata, 0, changed);
> +		if (local->ops->link_info_changed)
> +			local->ops->link_info_changed(&local->hw, &sdata->vif,
> +						      0, changed);
Hi Johannes,

I think you/someone will change here later for the "/* FIXME: should be 
for each link */", right?

It lead error/kernel crash as below while reconfig single MLO link which 
link id is 2.
When test with single MLO link which link id is 0, not found 
error/kernel crash.

I think it is because the sdata->vif.bss_conf link id is 0, but
the actual MLO link id is 2 when error/kernel crash happened.

Now I did a temp workaround to skip the crash.
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 061b5460799d..46249b9919ac 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -243,7 +243,8 @@ void ieee80211_bss_info_change_notify(struct 
ieee80211_sub_if_data *sdata,
local->ops->vif_cfg_changed(&local->hw, &sdata->vif, ch);
         }

-       if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
+       if (((!sdata->vif.valid_links) || (sdata->vif.valid_links & 
BIT(0))) &&
+           changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
                 u64 ch = changed & ~BSS_CHANGED_VIF_CFG_FLAGS;

                 /* FIXME: should be for each link */

kernel crash:
[  779.959413] BUG: kernel NULL pointer dereference, address: 
0000000000000000
[  779.959418] #PF: supervisor read access in kernel mode
[  779.959421] #PF: error_code(0x0000) - not-present page
[  779.959424] PGD 0 P4D 0
[  779.959429] Oops: 0000 [#1] PREEMPT SMP PTI
[  779.959433] CPU: 2 PID: 2603 Comm: kworker/2:0 Kdump: loaded Tainted: 
G        W  OE     5.19.0-rc6+ #4
[  779.959438] Hardware name: LENOVO 418065C/418065C, BIOS 83ET63WW 
(1.33 ) 07/29/2011
[  779.959442] Workqueue: events_freezable ieee80211_restart_work [mac80211]
[  779.959493] RIP: 0010:ath12k_mac_link_info_changed+0x31/0xc70 [ath12k]
[  779.959517] Code: 89 e5 41 57 41 56 49 89 d6 41 55 49 89 fd 41 54 49 
89 f4 53 48 89 cb 48 83 ec 48 65 48 8b 04 25 28 00 00 00 48 89 45 d0 31 
c0 <48> 8b 06 83 e1 40 48 89 45 a0 48 8b 40 08 48 89 45 a8 0f b6 46 08
[  779.959521] RSP: 0018:ffffbb7f4318bcf0 EFLAGS: 00010246
[  779.959525] RAX: 0000000000000000 RBX: 00000000021424fe RCX: 
00000000021424fe
[  779.959528] RDX: ffffa0878dd95bd8 RSI: 0000000000000000 RDI: 
ffffa08792b6a080
[  779.959531] RBP: ffffbb7f4318bd60 R08: ffffffffc0e8db90 R09: 
c00000010005e8a2
[  779.959534] R10: 0000000000000000 R11: ffffbb7f4318b6b0 R12: 
0000000000000000
[  779.959536] R13: ffffa08792b6a080 R14: ffffa0878dd95bd8 R15: 
ffffa08792b6a080
[  779.959539] FS:  0000000000000000(0000) GS:ffffa088ba280000(0000) 
knlGS:0000000000000000
[  779.959542] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  779.959545] CR2: 0000000000000000 CR3: 0000000103030006 CR4: 
00000000000606e0
[  779.959548] Call Trace:
[  779.959551]  <TASK>
[  779.959557]  ath12k_mac_op_link_info_changed+0x47/0x60 [ath12k]
[  779.959575]  ieee80211_bss_info_change_notify+0x182/0x2a0 [mac80211]
[  779.959617]  ieee80211_reconfig+0xc40/0x1570 [mac80211]
[  779.959672]  ? _raw_spin_unlock_irqrestore+0x27/0x43
[  779.959678]  ? try_to_del_timer_sync+0x53/0x80
[  779.959686]  ieee80211_restart_work+0xfe/0x160 [mac80211]
[  779.959726]  process_one_work+0x227/0x440
[  779.959732]  worker_thread+0x31/0x3e0
[  779.959736]  ? process_one_work+0x440/0x440
[  779.959739]  kthread+0xfe/0x130
[  779.959744]  ? kthread_complete_and_exit+0x20/0x20
[  779.959749]  ret_from_fork+0x22/0x30
[  779.959758]  </TASK>
[  779.959760] Modules linked in: michael_mic ath12k(OE) qmi_helpers 
qrtr_mhi mhi(E) qrtr mac80211(OE) cfg80211(OE) libarc4 rfcomm bnep 
nls_iso8859_1 intel_rapl_msr intel_rapl_common x86_pkg_temp_thermal 
intel_powerclamp coretemp kvm_intel kvm irqbypass snd_ctl_led 
crct10dif_pclmul ghash_clmulni_intel snd_hda_codec_conexant 
snd_hda_codec_hdmi snd_hda_codec_generic aesni_intel snd_hda_intel 
snd_intel_dspcfg snd_hda_codec crypto_simd cryptd rapl intel_cstate 
snd_hda_core snd_hwdep uvcvideo thinkpad_acpi videobuf2_vmalloc 
videobuf2_memops videobuf2_v4l2 nvram ledtrig_audio videobuf2_common 
videodev snd_pcm platform_profile snd_seq_midi snd_seq_midi_event mc 
btusb i915 btrtl btbcm btintel bluetooth cec rc_core snd_rawmidi 
drm_buddy ecdh_generic ecc snd_seq ttm drm_display_helper snd_seq_device 
snd_timer drm_kms_helper snd i2c_algo_bit fb_sys_fops syscopyarea 
sysfillrect sysimgblt soundcore mei_me mei at24 joydev input_leds 
serio_raw mac_hid wmi_bmof sch_fq_codel parport_pc ppdev lp parport drm
[  779.959856]  ip_tables x_tables autofs4 crc32_pclmul sdhci_pci e1000e 
firewire_ohci i2c_i801 ptp ahci pps_core psmouse libahci i2c_smbus 
firewire_core cqhci lpc_ich sdhci crc_itu_t wmi video
[  779.959883] CR2: 0000000000000000
> +	}
> +
> +	if (local->ops->bss_info_changed)
> +		local->ops->bss_info_changed(&local->hw, &sdata->vif,
> +					     &sdata->vif.bss_conf, changed);
> +	trace_drv_return_void(local);
> +}
> +
...

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  8:47     ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18  8:47 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: Johannes Berg, ath11k, ath12k

On 6/1/2022 3:39 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Split the bss_info_changed method to vif_cfg_changed and
> link_info_changed, with the latter getting a link ID.
> Also change the 'changed' parameter to u64 already, we
> know we need that.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>   
...
> diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> index 0c81ae492df4..6165b90bf0e2 100644
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -199,15 +199,84 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
>   	return ret;
>   }
>   
> +#define BSS_CHANGED_VIF_CFG_FLAGS (BSS_CHANGED_ASSOC |\
> +				   BSS_CHANGED_IDLE |\
> +				   BSS_CHANGED_IBSS |\
> +				   BSS_CHANGED_ARP_FILTER |\
> +				   BSS_CHANGED_SSID)
> +
>   void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
> -				      u32 changed)
> +				      u64 changed)
>   {
>   	struct ieee80211_local *local = sdata->local;
>   
> +	might_sleep();
> +
>   	if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
>   		return;
>   
> -	drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
> +	if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON |
> +				    BSS_CHANGED_BEACON_ENABLED) &&
> +			 sdata->vif.type != NL80211_IFTYPE_AP &&
> +			 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
> +			 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
> +			 sdata->vif.type != NL80211_IFTYPE_OCB))
> +		return;
> +
> +	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
> +			 sdata->vif.type == NL80211_IFTYPE_NAN ||
> +			 (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
> +			  !sdata->vif.bss_conf.mu_mimo_owner &&
> +			  !(changed & BSS_CHANGED_TXPOWER))))
> +		return;
> +
> +	if (!check_sdata_in_driver(sdata))
> +		return;
> +
> +	if (changed & BSS_CHANGED_VIF_CFG_FLAGS) {
> +		trace_drv_vif_cfg_changed(local, sdata, changed);
> +		if (local->ops->vif_cfg_changed)
> +			local->ops->vif_cfg_changed(&local->hw, &sdata->vif, changed);
> +	}
> +
> +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
> +		/* FIXME: should be for each link */
> +		trace_drv_link_info_changed(local, sdata, 0, changed);
> +		if (local->ops->link_info_changed)
> +			local->ops->link_info_changed(&local->hw, &sdata->vif,
> +						      0, changed);
Hi Johannes,

I think you/someone will change here later for the "/* FIXME: should be 
for each link */", right?

It lead error/kernel crash as below while reconfig single MLO link which 
link id is 2.
When test with single MLO link which link id is 0, not found 
error/kernel crash.

I think it is because the sdata->vif.bss_conf link id is 0, but
the actual MLO link id is 2 when error/kernel crash happened.

Now I did a temp workaround to skip the crash.
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 061b5460799d..46249b9919ac 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -243,7 +243,8 @@ void ieee80211_bss_info_change_notify(struct 
ieee80211_sub_if_data *sdata,
local->ops->vif_cfg_changed(&local->hw, &sdata->vif, ch);
         }

-       if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
+       if (((!sdata->vif.valid_links) || (sdata->vif.valid_links & 
BIT(0))) &&
+           changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
                 u64 ch = changed & ~BSS_CHANGED_VIF_CFG_FLAGS;

                 /* FIXME: should be for each link */

kernel crash:
[  779.959413] BUG: kernel NULL pointer dereference, address: 
0000000000000000
[  779.959418] #PF: supervisor read access in kernel mode
[  779.959421] #PF: error_code(0x0000) - not-present page
[  779.959424] PGD 0 P4D 0
[  779.959429] Oops: 0000 [#1] PREEMPT SMP PTI
[  779.959433] CPU: 2 PID: 2603 Comm: kworker/2:0 Kdump: loaded Tainted: 
G        W  OE     5.19.0-rc6+ #4
[  779.959438] Hardware name: LENOVO 418065C/418065C, BIOS 83ET63WW 
(1.33 ) 07/29/2011
[  779.959442] Workqueue: events_freezable ieee80211_restart_work [mac80211]
[  779.959493] RIP: 0010:ath12k_mac_link_info_changed+0x31/0xc70 [ath12k]
[  779.959517] Code: 89 e5 41 57 41 56 49 89 d6 41 55 49 89 fd 41 54 49 
89 f4 53 48 89 cb 48 83 ec 48 65 48 8b 04 25 28 00 00 00 48 89 45 d0 31 
c0 <48> 8b 06 83 e1 40 48 89 45 a0 48 8b 40 08 48 89 45 a8 0f b6 46 08
[  779.959521] RSP: 0018:ffffbb7f4318bcf0 EFLAGS: 00010246
[  779.959525] RAX: 0000000000000000 RBX: 00000000021424fe RCX: 
00000000021424fe
[  779.959528] RDX: ffffa0878dd95bd8 RSI: 0000000000000000 RDI: 
ffffa08792b6a080
[  779.959531] RBP: ffffbb7f4318bd60 R08: ffffffffc0e8db90 R09: 
c00000010005e8a2
[  779.959534] R10: 0000000000000000 R11: ffffbb7f4318b6b0 R12: 
0000000000000000
[  779.959536] R13: ffffa08792b6a080 R14: ffffa0878dd95bd8 R15: 
ffffa08792b6a080
[  779.959539] FS:  0000000000000000(0000) GS:ffffa088ba280000(0000) 
knlGS:0000000000000000
[  779.959542] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  779.959545] CR2: 0000000000000000 CR3: 0000000103030006 CR4: 
00000000000606e0
[  779.959548] Call Trace:
[  779.959551]  <TASK>
[  779.959557]  ath12k_mac_op_link_info_changed+0x47/0x60 [ath12k]
[  779.959575]  ieee80211_bss_info_change_notify+0x182/0x2a0 [mac80211]
[  779.959617]  ieee80211_reconfig+0xc40/0x1570 [mac80211]
[  779.959672]  ? _raw_spin_unlock_irqrestore+0x27/0x43
[  779.959678]  ? try_to_del_timer_sync+0x53/0x80
[  779.959686]  ieee80211_restart_work+0xfe/0x160 [mac80211]
[  779.959726]  process_one_work+0x227/0x440
[  779.959732]  worker_thread+0x31/0x3e0
[  779.959736]  ? process_one_work+0x440/0x440
[  779.959739]  kthread+0xfe/0x130
[  779.959744]  ? kthread_complete_and_exit+0x20/0x20
[  779.959749]  ret_from_fork+0x22/0x30
[  779.959758]  </TASK>
[  779.959760] Modules linked in: michael_mic ath12k(OE) qmi_helpers 
qrtr_mhi mhi(E) qrtr mac80211(OE) cfg80211(OE) libarc4 rfcomm bnep 
nls_iso8859_1 intel_rapl_msr intel_rapl_common x86_pkg_temp_thermal 
intel_powerclamp coretemp kvm_intel kvm irqbypass snd_ctl_led 
crct10dif_pclmul ghash_clmulni_intel snd_hda_codec_conexant 
snd_hda_codec_hdmi snd_hda_codec_generic aesni_intel snd_hda_intel 
snd_intel_dspcfg snd_hda_codec crypto_simd cryptd rapl intel_cstate 
snd_hda_core snd_hwdep uvcvideo thinkpad_acpi videobuf2_vmalloc 
videobuf2_memops videobuf2_v4l2 nvram ledtrig_audio videobuf2_common 
videodev snd_pcm platform_profile snd_seq_midi snd_seq_midi_event mc 
btusb i915 btrtl btbcm btintel bluetooth cec rc_core snd_rawmidi 
drm_buddy ecdh_generic ecc snd_seq ttm drm_display_helper snd_seq_device 
snd_timer drm_kms_helper snd i2c_algo_bit fb_sys_fops syscopyarea 
sysfillrect sysimgblt soundcore mei_me mei at24 joydev input_leds 
serio_raw mac_hid wmi_bmof sch_fq_codel parport_pc ppdev lp parport drm
[  779.959856]  ip_tables x_tables autofs4 crc32_pclmul sdhci_pci e1000e 
firewire_ohci i2c_i801 ptp ahci pps_core psmouse libahci i2c_smbus 
firewire_core cqhci lpc_ich sdhci crc_itu_t wmi video
[  779.959883] CR2: 0000000000000000
> +	}
> +
> +	if (local->ops->bss_info_changed)
> +		local->ops->bss_info_changed(&local->hw, &sdata->vif,
> +					     &sdata->vif.bss_conf, changed);
> +	trace_drv_return_void(local);
> +}
> +
...

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  8:47     ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18  8:47 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: Johannes Berg, ath11k, ath12k

On 6/1/2022 3:39 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Split the bss_info_changed method to vif_cfg_changed and
> link_info_changed, with the latter getting a link ID.
> Also change the 'changed' parameter to u64 already, we
> know we need that.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>   
...
> diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> index 0c81ae492df4..6165b90bf0e2 100644
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -199,15 +199,84 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
>   	return ret;
>   }
>   
> +#define BSS_CHANGED_VIF_CFG_FLAGS (BSS_CHANGED_ASSOC |\
> +				   BSS_CHANGED_IDLE |\
> +				   BSS_CHANGED_IBSS |\
> +				   BSS_CHANGED_ARP_FILTER |\
> +				   BSS_CHANGED_SSID)
> +
>   void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
> -				      u32 changed)
> +				      u64 changed)
>   {
>   	struct ieee80211_local *local = sdata->local;
>   
> +	might_sleep();
> +
>   	if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
>   		return;
>   
> -	drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
> +	if (WARN_ON_ONCE(changed & (BSS_CHANGED_BEACON |
> +				    BSS_CHANGED_BEACON_ENABLED) &&
> +			 sdata->vif.type != NL80211_IFTYPE_AP &&
> +			 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
> +			 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
> +			 sdata->vif.type != NL80211_IFTYPE_OCB))
> +		return;
> +
> +	if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
> +			 sdata->vif.type == NL80211_IFTYPE_NAN ||
> +			 (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
> +			  !sdata->vif.bss_conf.mu_mimo_owner &&
> +			  !(changed & BSS_CHANGED_TXPOWER))))
> +		return;
> +
> +	if (!check_sdata_in_driver(sdata))
> +		return;
> +
> +	if (changed & BSS_CHANGED_VIF_CFG_FLAGS) {
> +		trace_drv_vif_cfg_changed(local, sdata, changed);
> +		if (local->ops->vif_cfg_changed)
> +			local->ops->vif_cfg_changed(&local->hw, &sdata->vif, changed);
> +	}
> +
> +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
> +		/* FIXME: should be for each link */
> +		trace_drv_link_info_changed(local, sdata, 0, changed);
> +		if (local->ops->link_info_changed)
> +			local->ops->link_info_changed(&local->hw, &sdata->vif,
> +						      0, changed);
Hi Johannes,

I think you/someone will change here later for the "/* FIXME: should be 
for each link */", right?

It lead error/kernel crash as below while reconfig single MLO link which 
link id is 2.
When test with single MLO link which link id is 0, not found 
error/kernel crash.

I think it is because the sdata->vif.bss_conf link id is 0, but
the actual MLO link id is 2 when error/kernel crash happened.

Now I did a temp workaround to skip the crash.
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 061b5460799d..46249b9919ac 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -243,7 +243,8 @@ void ieee80211_bss_info_change_notify(struct 
ieee80211_sub_if_data *sdata,
local->ops->vif_cfg_changed(&local->hw, &sdata->vif, ch);
         }

-       if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
+       if (((!sdata->vif.valid_links) || (sdata->vif.valid_links & 
BIT(0))) &&
+           changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
                 u64 ch = changed & ~BSS_CHANGED_VIF_CFG_FLAGS;

                 /* FIXME: should be for each link */

kernel crash:
[  779.959413] BUG: kernel NULL pointer dereference, address: 
0000000000000000
[  779.959418] #PF: supervisor read access in kernel mode
[  779.959421] #PF: error_code(0x0000) - not-present page
[  779.959424] PGD 0 P4D 0
[  779.959429] Oops: 0000 [#1] PREEMPT SMP PTI
[  779.959433] CPU: 2 PID: 2603 Comm: kworker/2:0 Kdump: loaded Tainted: 
G        W  OE     5.19.0-rc6+ #4
[  779.959438] Hardware name: LENOVO 418065C/418065C, BIOS 83ET63WW 
(1.33 ) 07/29/2011
[  779.959442] Workqueue: events_freezable ieee80211_restart_work [mac80211]
[  779.959493] RIP: 0010:ath12k_mac_link_info_changed+0x31/0xc70 [ath12k]
[  779.959517] Code: 89 e5 41 57 41 56 49 89 d6 41 55 49 89 fd 41 54 49 
89 f4 53 48 89 cb 48 83 ec 48 65 48 8b 04 25 28 00 00 00 48 89 45 d0 31 
c0 <48> 8b 06 83 e1 40 48 89 45 a0 48 8b 40 08 48 89 45 a8 0f b6 46 08
[  779.959521] RSP: 0018:ffffbb7f4318bcf0 EFLAGS: 00010246
[  779.959525] RAX: 0000000000000000 RBX: 00000000021424fe RCX: 
00000000021424fe
[  779.959528] RDX: ffffa0878dd95bd8 RSI: 0000000000000000 RDI: 
ffffa08792b6a080
[  779.959531] RBP: ffffbb7f4318bd60 R08: ffffffffc0e8db90 R09: 
c00000010005e8a2
[  779.959534] R10: 0000000000000000 R11: ffffbb7f4318b6b0 R12: 
0000000000000000
[  779.959536] R13: ffffa08792b6a080 R14: ffffa0878dd95bd8 R15: 
ffffa08792b6a080
[  779.959539] FS:  0000000000000000(0000) GS:ffffa088ba280000(0000) 
knlGS:0000000000000000
[  779.959542] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  779.959545] CR2: 0000000000000000 CR3: 0000000103030006 CR4: 
00000000000606e0
[  779.959548] Call Trace:
[  779.959551]  <TASK>
[  779.959557]  ath12k_mac_op_link_info_changed+0x47/0x60 [ath12k]
[  779.959575]  ieee80211_bss_info_change_notify+0x182/0x2a0 [mac80211]
[  779.959617]  ieee80211_reconfig+0xc40/0x1570 [mac80211]
[  779.959672]  ? _raw_spin_unlock_irqrestore+0x27/0x43
[  779.959678]  ? try_to_del_timer_sync+0x53/0x80
[  779.959686]  ieee80211_restart_work+0xfe/0x160 [mac80211]
[  779.959726]  process_one_work+0x227/0x440
[  779.959732]  worker_thread+0x31/0x3e0
[  779.959736]  ? process_one_work+0x440/0x440
[  779.959739]  kthread+0xfe/0x130
[  779.959744]  ? kthread_complete_and_exit+0x20/0x20
[  779.959749]  ret_from_fork+0x22/0x30
[  779.959758]  </TASK>
[  779.959760] Modules linked in: michael_mic ath12k(OE) qmi_helpers 
qrtr_mhi mhi(E) qrtr mac80211(OE) cfg80211(OE) libarc4 rfcomm bnep 
nls_iso8859_1 intel_rapl_msr intel_rapl_common x86_pkg_temp_thermal 
intel_powerclamp coretemp kvm_intel kvm irqbypass snd_ctl_led 
crct10dif_pclmul ghash_clmulni_intel snd_hda_codec_conexant 
snd_hda_codec_hdmi snd_hda_codec_generic aesni_intel snd_hda_intel 
snd_intel_dspcfg snd_hda_codec crypto_simd cryptd rapl intel_cstate 
snd_hda_core snd_hwdep uvcvideo thinkpad_acpi videobuf2_vmalloc 
videobuf2_memops videobuf2_v4l2 nvram ledtrig_audio videobuf2_common 
videodev snd_pcm platform_profile snd_seq_midi snd_seq_midi_event mc 
btusb i915 btrtl btbcm btintel bluetooth cec rc_core snd_rawmidi 
drm_buddy ecdh_generic ecc snd_seq ttm drm_display_helper snd_seq_device 
snd_timer drm_kms_helper snd i2c_algo_bit fb_sys_fops syscopyarea 
sysfillrect sysimgblt soundcore mei_me mei at24 joydev input_leds 
serio_raw mac_hid wmi_bmof sch_fq_codel parport_pc ppdev lp parport drm
[  779.959856]  ip_tables x_tables autofs4 crc32_pclmul sdhci_pci e1000e 
firewire_ohci i2c_i801 ptp ahci pps_core psmouse libahci i2c_smbus 
firewire_core cqhci lpc_ich sdhci crc_itu_t wmi video
[  779.959883] CR2: 0000000000000000
> +	}
> +
> +	if (local->ops->bss_info_changed)
> +		local->ops->bss_info_changed(&local->hw, &sdata->vif,
> +					     &sdata->vif.bss_conf, changed);
> +	trace_drv_return_void(local);
> +}
> +
...

-- 
ath12k mailing list
ath12k@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/ath12k

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-10-18  8:47     ` Wen Gong
  (?)
@ 2022-10-18  8:50       ` Johannes Berg
  -1 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-10-18  8:50 UTC (permalink / raw)
  To: Wen Gong, linux-wireless; +Cc: ath11k, ath12k

On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
> 
> > +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
> > +		/* FIXME: should be for each link */
> > +		trace_drv_link_info_changed(local, sdata, 0, changed);
> > +		if (local->ops->link_info_changed)
> > +			local->ops->link_info_changed(&local->hw, &sdata->vif,
> > +						      0, changed);
> 
> I think you/someone will change here later for the "/* FIXME: should be 
> for each link */", right?

Maybe. I'm not actually sure it's really needed, it depends how we use
this in the future.

> It lead error/kernel crash as below while reconfig single MLO link which 
> link id is 2.
> When test with single MLO link which link id is 0, not found 
> error/kernel crash.

I'm not surprised, I just worked on fixing reconfig in the last few
days, will post it after some more review/testing.

So I think that might not need changes *here*, but rather a proper FW
restart. Which I haven't tested in AP mode though -- was the crash in AP
mode?

johannes

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  8:50       ` Johannes Berg
  0 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-10-18  8:50 UTC (permalink / raw)
  To: Wen Gong, linux-wireless; +Cc: ath11k, ath12k

On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
> 
> > +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
> > +		/* FIXME: should be for each link */
> > +		trace_drv_link_info_changed(local, sdata, 0, changed);
> > +		if (local->ops->link_info_changed)
> > +			local->ops->link_info_changed(&local->hw, &sdata->vif,
> > +						      0, changed);
> 
> I think you/someone will change here later for the "/* FIXME: should be 
> for each link */", right?

Maybe. I'm not actually sure it's really needed, it depends how we use
this in the future.

> It lead error/kernel crash as below while reconfig single MLO link which 
> link id is 2.
> When test with single MLO link which link id is 0, not found 
> error/kernel crash.

I'm not surprised, I just worked on fixing reconfig in the last few
days, will post it after some more review/testing.

So I think that might not need changes *here*, but rather a proper FW
restart. Which I haven't tested in AP mode though -- was the crash in AP
mode?

johannes

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  8:50       ` Johannes Berg
  0 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-10-18  8:50 UTC (permalink / raw)
  To: Wen Gong, linux-wireless; +Cc: ath11k, ath12k

On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
> 
> > +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
> > +		/* FIXME: should be for each link */
> > +		trace_drv_link_info_changed(local, sdata, 0, changed);
> > +		if (local->ops->link_info_changed)
> > +			local->ops->link_info_changed(&local->hw, &sdata->vif,
> > +						      0, changed);
> 
> I think you/someone will change here later for the "/* FIXME: should be 
> for each link */", right?

Maybe. I'm not actually sure it's really needed, it depends how we use
this in the future.

> It lead error/kernel crash as below while reconfig single MLO link which 
> link id is 2.
> When test with single MLO link which link id is 0, not found 
> error/kernel crash.

I'm not surprised, I just worked on fixing reconfig in the last few
days, will post it after some more review/testing.

So I think that might not need changes *here*, but rather a proper FW
restart. Which I haven't tested in AP mode though -- was the crash in AP
mode?

johannes

-- 
ath12k mailing list
ath12k@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/ath12k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-10-18  8:50       ` Johannes Berg
  (?)
@ 2022-10-18  8:52         ` Wen Gong
  -1 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18  8:52 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 4:50 PM, Johannes Berg wrote:
> On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
>>> +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
>>> +		/* FIXME: should be for each link */
>>> +		trace_drv_link_info_changed(local, sdata, 0, changed);
>>> +		if (local->ops->link_info_changed)
>>> +			local->ops->link_info_changed(&local->hw, &sdata->vif,
>>> +						      0, changed);
>> I think you/someone will change here later for the "/* FIXME: should be
>> for each link */", right?
> Maybe. I'm not actually sure it's really needed, it depends how we use
> this in the future.
>
>> It lead error/kernel crash as below while reconfig single MLO link which
>> link id is 2.
>> When test with single MLO link which link id is 0, not found
>> error/kernel crash.
> I'm not surprised, I just worked on fixing reconfig in the last few
> days, will post it after some more review/testing.
Thanks.
> So I think that might not need changes *here*, but rather a proper FW
> restart. Which I haven't tested in AP mode though -- was the crash in AP
> mode?
It is crash in station mode.
> johannes

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  8:52         ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18  8:52 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 4:50 PM, Johannes Berg wrote:
> On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
>>> +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
>>> +		/* FIXME: should be for each link */
>>> +		trace_drv_link_info_changed(local, sdata, 0, changed);
>>> +		if (local->ops->link_info_changed)
>>> +			local->ops->link_info_changed(&local->hw, &sdata->vif,
>>> +						      0, changed);
>> I think you/someone will change here later for the "/* FIXME: should be
>> for each link */", right?
> Maybe. I'm not actually sure it's really needed, it depends how we use
> this in the future.
>
>> It lead error/kernel crash as below while reconfig single MLO link which
>> link id is 2.
>> When test with single MLO link which link id is 0, not found
>> error/kernel crash.
> I'm not surprised, I just worked on fixing reconfig in the last few
> days, will post it after some more review/testing.
Thanks.
> So I think that might not need changes *here*, but rather a proper FW
> restart. Which I haven't tested in AP mode though -- was the crash in AP
> mode?
It is crash in station mode.
> johannes

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  8:52         ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18  8:52 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 4:50 PM, Johannes Berg wrote:
> On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
>>> +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
>>> +		/* FIXME: should be for each link */
>>> +		trace_drv_link_info_changed(local, sdata, 0, changed);
>>> +		if (local->ops->link_info_changed)
>>> +			local->ops->link_info_changed(&local->hw, &sdata->vif,
>>> +						      0, changed);
>> I think you/someone will change here later for the "/* FIXME: should be
>> for each link */", right?
> Maybe. I'm not actually sure it's really needed, it depends how we use
> this in the future.
>
>> It lead error/kernel crash as below while reconfig single MLO link which
>> link id is 2.
>> When test with single MLO link which link id is 0, not found
>> error/kernel crash.
> I'm not surprised, I just worked on fixing reconfig in the last few
> days, will post it after some more review/testing.
Thanks.
> So I think that might not need changes *here*, but rather a proper FW
> restart. Which I haven't tested in AP mode though -- was the crash in AP
> mode?
It is crash in station mode.
> johannes

-- 
ath12k mailing list
ath12k@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/ath12k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-10-18  8:52         ` Wen Gong
  (?)
@ 2022-10-18  8:53           ` Johannes Berg
  -1 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-10-18  8:53 UTC (permalink / raw)
  To: Wen Gong, linux-wireless; +Cc: ath11k, ath12k

On Tue, 2022-10-18 at 16:52 +0800, Wen Gong wrote:
> On 10/18/2022 4:50 PM, Johannes Berg wrote:
> > On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
> > > > +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
> > > > +		/* FIXME: should be for each link */
> > > > +		trace_drv_link_info_changed(local, sdata, 0, changed);
> > > > +		if (local->ops->link_info_changed)
> > > > +			local->ops->link_info_changed(&local->hw, &sdata->vif,
> > > > +						      0, changed);
> > > I think you/someone will change here later for the "/* FIXME: should be
> > > for each link */", right?
> > Maybe. I'm not actually sure it's really needed, it depends how we use
> > this in the future.
> > 
> > > It lead error/kernel crash as below while reconfig single MLO link which
> > > link id is 2.
> > > When test with single MLO link which link id is 0, not found
> > > error/kernel crash.
> > I'm not surprised, I just worked on fixing reconfig in the last few
> > days, will post it after some more review/testing.
> Thanks.
> > So I think that might not need changes *here*, but rather a proper FW
> > restart. Which I haven't tested in AP mode though -- was the crash in AP
> > mode?
> It is crash in station mode.

try this?

https://p.sipsolutions.net/0652bbbbe350b126.txt

johannes

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  8:53           ` Johannes Berg
  0 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-10-18  8:53 UTC (permalink / raw)
  To: Wen Gong, linux-wireless; +Cc: ath11k, ath12k

On Tue, 2022-10-18 at 16:52 +0800, Wen Gong wrote:
> On 10/18/2022 4:50 PM, Johannes Berg wrote:
> > On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
> > > > +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
> > > > +		/* FIXME: should be for each link */
> > > > +		trace_drv_link_info_changed(local, sdata, 0, changed);
> > > > +		if (local->ops->link_info_changed)
> > > > +			local->ops->link_info_changed(&local->hw, &sdata->vif,
> > > > +						      0, changed);
> > > I think you/someone will change here later for the "/* FIXME: should be
> > > for each link */", right?
> > Maybe. I'm not actually sure it's really needed, it depends how we use
> > this in the future.
> > 
> > > It lead error/kernel crash as below while reconfig single MLO link which
> > > link id is 2.
> > > When test with single MLO link which link id is 0, not found
> > > error/kernel crash.
> > I'm not surprised, I just worked on fixing reconfig in the last few
> > days, will post it after some more review/testing.
> Thanks.
> > So I think that might not need changes *here*, but rather a proper FW
> > restart. Which I haven't tested in AP mode though -- was the crash in AP
> > mode?
> It is crash in station mode.

try this?

https://p.sipsolutions.net/0652bbbbe350b126.txt

johannes

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  8:53           ` Johannes Berg
  0 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-10-18  8:53 UTC (permalink / raw)
  To: Wen Gong, linux-wireless; +Cc: ath11k, ath12k

On Tue, 2022-10-18 at 16:52 +0800, Wen Gong wrote:
> On 10/18/2022 4:50 PM, Johannes Berg wrote:
> > On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
> > > > +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
> > > > +		/* FIXME: should be for each link */
> > > > +		trace_drv_link_info_changed(local, sdata, 0, changed);
> > > > +		if (local->ops->link_info_changed)
> > > > +			local->ops->link_info_changed(&local->hw, &sdata->vif,
> > > > +						      0, changed);
> > > I think you/someone will change here later for the "/* FIXME: should be
> > > for each link */", right?
> > Maybe. I'm not actually sure it's really needed, it depends how we use
> > this in the future.
> > 
> > > It lead error/kernel crash as below while reconfig single MLO link which
> > > link id is 2.
> > > When test with single MLO link which link id is 0, not found
> > > error/kernel crash.
> > I'm not surprised, I just worked on fixing reconfig in the last few
> > days, will post it after some more review/testing.
> Thanks.
> > So I think that might not need changes *here*, but rather a proper FW
> > restart. Which I haven't tested in AP mode though -- was the crash in AP
> > mode?
> It is crash in station mode.

try this?

https://p.sipsolutions.net/0652bbbbe350b126.txt

johannes

-- 
ath12k mailing list
ath12k@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/ath12k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-10-18  8:53           ` Johannes Berg
  (?)
@ 2022-10-18  9:50             ` Wen Gong
  -1 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18  9:50 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 4:53 PM, Johannes Berg wrote:
> On Tue, 2022-10-18 at 16:52 +0800, Wen Gong wrote:
>> On 10/18/2022 4:50 PM, Johannes Berg wrote:
>>> On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
>>>>> +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
>>>>> +		/* FIXME: should be for each link */
>>>>> +		trace_drv_link_info_changed(local, sdata, 0, changed);
>>>>> +		if (local->ops->link_info_changed)
>>>>> +			local->ops->link_info_changed(&local->hw, &sdata->vif,
>>>>> +						      0, changed);
>>>> I think you/someone will change here later for the "/* FIXME: should be
>>>> for each link */", right?
>>> Maybe. I'm not actually sure it's really needed, it depends how we use
>>> this in the future.
>>>
>>>> It lead error/kernel crash as below while reconfig single MLO link which
>>>> link id is 2.
>>>> When test with single MLO link which link id is 0, not found
>>>> error/kernel crash.
>>> I'm not surprised, I just worked on fixing reconfig in the last few
>>> days, will post it after some more review/testing.
>> Thanks.
>>> So I think that might not need changes *here*, but rather a proper FW
>>> restart. Which I haven't tested in AP mode though -- was the crash in AP
>>> mode?
>> It is crash in station mode.
> try this?
>
> https://p.sipsolutions.net/0652bbbbe350b126.txt
>
> johannes

Conflict happened while run "git am" the patch.

Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my 
local code,

also it is missing in 
https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c

Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your 
local code?


-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  9:50             ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18  9:50 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 4:53 PM, Johannes Berg wrote:
> On Tue, 2022-10-18 at 16:52 +0800, Wen Gong wrote:
>> On 10/18/2022 4:50 PM, Johannes Berg wrote:
>>> On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
>>>>> +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
>>>>> +		/* FIXME: should be for each link */
>>>>> +		trace_drv_link_info_changed(local, sdata, 0, changed);
>>>>> +		if (local->ops->link_info_changed)
>>>>> +			local->ops->link_info_changed(&local->hw, &sdata->vif,
>>>>> +						      0, changed);
>>>> I think you/someone will change here later for the "/* FIXME: should be
>>>> for each link */", right?
>>> Maybe. I'm not actually sure it's really needed, it depends how we use
>>> this in the future.
>>>
>>>> It lead error/kernel crash as below while reconfig single MLO link which
>>>> link id is 2.
>>>> When test with single MLO link which link id is 0, not found
>>>> error/kernel crash.
>>> I'm not surprised, I just worked on fixing reconfig in the last few
>>> days, will post it after some more review/testing.
>> Thanks.
>>> So I think that might not need changes *here*, but rather a proper FW
>>> restart. Which I haven't tested in AP mode though -- was the crash in AP
>>> mode?
>> It is crash in station mode.
> try this?
>
> https://p.sipsolutions.net/0652bbbbe350b126.txt
>
> johannes

Conflict happened while run "git am" the patch.

Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my 
local code,

also it is missing in 
https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c

Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your 
local code?


-- 
ath12k mailing list
ath12k@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/ath12k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  9:50             ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18  9:50 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 4:53 PM, Johannes Berg wrote:
> On Tue, 2022-10-18 at 16:52 +0800, Wen Gong wrote:
>> On 10/18/2022 4:50 PM, Johannes Berg wrote:
>>> On Tue, 2022-10-18 at 16:47 +0800, Wen Gong wrote:
>>>>> +	if (changed & ~BSS_CHANGED_VIF_CFG_FLAGS) {
>>>>> +		/* FIXME: should be for each link */
>>>>> +		trace_drv_link_info_changed(local, sdata, 0, changed);
>>>>> +		if (local->ops->link_info_changed)
>>>>> +			local->ops->link_info_changed(&local->hw, &sdata->vif,
>>>>> +						      0, changed);
>>>> I think you/someone will change here later for the "/* FIXME: should be
>>>> for each link */", right?
>>> Maybe. I'm not actually sure it's really needed, it depends how we use
>>> this in the future.
>>>
>>>> It lead error/kernel crash as below while reconfig single MLO link which
>>>> link id is 2.
>>>> When test with single MLO link which link id is 0, not found
>>>> error/kernel crash.
>>> I'm not surprised, I just worked on fixing reconfig in the last few
>>> days, will post it after some more review/testing.
>> Thanks.
>>> So I think that might not need changes *here*, but rather a proper FW
>>> restart. Which I haven't tested in AP mode though -- was the crash in AP
>>> mode?
>> It is crash in station mode.
> try this?
>
> https://p.sipsolutions.net/0652bbbbe350b126.txt
>
> johannes

Conflict happened while run "git am" the patch.

Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my 
local code,

also it is missing in 
https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c

Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your 
local code?


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-10-18  9:50             ` Wen Gong
  (?)
@ 2022-10-18  9:51               ` Johannes Berg
  -1 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-10-18  9:51 UTC (permalink / raw)
  To: Wen Gong, linux-wireless; +Cc: ath11k, ath12k

On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
> > 
> > https://p.sipsolutions.net/0652bbbbe350b126.txt
> 
> Conflict happened while run "git am" the patch.
> 
> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my 
> local code,
> 
> also it is missing in 
> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c
> 
> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your 
> local code?
> 

Ah yes, we didn't upstream that because there's still this discussion
about handling puncturing. But you can probably apply around that.

johannes

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  9:51               ` Johannes Berg
  0 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-10-18  9:51 UTC (permalink / raw)
  To: Wen Gong, linux-wireless; +Cc: ath11k, ath12k

On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
> > 
> > https://p.sipsolutions.net/0652bbbbe350b126.txt
> 
> Conflict happened while run "git am" the patch.
> 
> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my 
> local code,
> 
> also it is missing in 
> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c
> 
> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your 
> local code?
> 

Ah yes, we didn't upstream that because there's still this discussion
about handling puncturing. But you can probably apply around that.

johannes

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18  9:51               ` Johannes Berg
  0 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2022-10-18  9:51 UTC (permalink / raw)
  To: Wen Gong, linux-wireless; +Cc: ath11k, ath12k

On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
> > 
> > https://p.sipsolutions.net/0652bbbbe350b126.txt
> 
> Conflict happened while run "git am" the patch.
> 
> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my 
> local code,
> 
> also it is missing in 
> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c
> 
> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your 
> local code?
> 

Ah yes, we didn't upstream that because there's still this discussion
about handling puncturing. But you can probably apply around that.

johannes

-- 
ath12k mailing list
ath12k@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/ath12k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-10-18  9:51               ` Johannes Berg
  (?)
@ 2022-10-18 10:10                 ` Wen Gong
  -1 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18 10:10 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 5:51 PM, Johannes Berg wrote:
> On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
>>> https://p.sipsolutions.net/0652bbbbe350b126.txt
>> Conflict happened while run "git am" the patch.
>>
>> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my
>> local code,
>>
>> also it is missing in
>> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c
>>
>> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your
>> local code?
>>
> Ah yes, we didn't upstream that because there's still this discussion
> about handling puncturing. But you can probably apply around that.
>
> johannes

Yes, after apply it.

and apply "commit 3d901102922723eedce6ef10ebd03315a7abb8a5 wifi: 
mac80211: implement link switching" to

fix build error because my local code is not latest.

it is built success, I will try it later.


-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18 10:10                 ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18 10:10 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 5:51 PM, Johannes Berg wrote:
> On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
>>> https://p.sipsolutions.net/0652bbbbe350b126.txt
>> Conflict happened while run "git am" the patch.
>>
>> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my
>> local code,
>>
>> also it is missing in
>> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c
>>
>> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your
>> local code?
>>
> Ah yes, we didn't upstream that because there's still this discussion
> about handling puncturing. But you can probably apply around that.
>
> johannes

Yes, after apply it.

and apply "commit 3d901102922723eedce6ef10ebd03315a7abb8a5 wifi: 
mac80211: implement link switching" to

fix build error because my local code is not latest.

it is built success, I will try it later.


-- 
ath12k mailing list
ath12k@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/ath12k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-18 10:10                 ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-18 10:10 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 5:51 PM, Johannes Berg wrote:
> On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
>>> https://p.sipsolutions.net/0652bbbbe350b126.txt
>> Conflict happened while run "git am" the patch.
>>
>> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my
>> local code,
>>
>> also it is missing in
>> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c
>>
>> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your
>> local code?
>>
> Ah yes, we didn't upstream that because there's still this discussion
> about handling puncturing. But you can probably apply around that.
>
> johannes

Yes, after apply it.

and apply "commit 3d901102922723eedce6ef10ebd03315a7abb8a5 wifi: 
mac80211: implement link switching" to

fix build error because my local code is not latest.

it is built success, I will try it later.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-10-18 10:10                 ` Wen Gong
  (?)
@ 2022-10-19  4:32                   ` Wen Gong
  -1 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-19  4:32 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 6:10 PM, Wen Gong wrote:
> On 10/18/2022 5:51 PM, Johannes Berg wrote:
>> On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
>>>> https://p.sipsolutions.net/0652bbbbe350b126.txt
>>> Conflict happened while run "git am" the patch.
>>>
>>> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my
>>> local code,
>>>
>>> also it is missing in
>>> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c 
>>>
>>>
>>> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your
>>> local code?
>>>
>> Ah yes, we didn't upstream that because there's still this discussion
>> about handling puncturing. But you can probably apply around that.
>>
>> johannes
>
> Yes, after apply it.
>
> and apply "commit 3d901102922723eedce6ef10ebd03315a7abb8a5 wifi: 
> mac80211: implement link switching" to
>
> fix build error because my local code is not latest.
>
> it is built success, I will try it later.
>
Hi johannes,

After above change, no error/kernel crash happened while reconfig single 
MLO link which link id is 2.


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-19  4:32                   ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-19  4:32 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 6:10 PM, Wen Gong wrote:
> On 10/18/2022 5:51 PM, Johannes Berg wrote:
>> On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
>>>> https://p.sipsolutions.net/0652bbbbe350b126.txt
>>> Conflict happened while run "git am" the patch.
>>>
>>> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my
>>> local code,
>>>
>>> also it is missing in
>>> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c 
>>>
>>>
>>> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your
>>> local code?
>>>
>> Ah yes, we didn't upstream that because there's still this discussion
>> about handling puncturing. But you can probably apply around that.
>>
>> johannes
>
> Yes, after apply it.
>
> and apply "commit 3d901102922723eedce6ef10ebd03315a7abb8a5 wifi: 
> mac80211: implement link switching" to
>
> fix build error because my local code is not latest.
>
> it is built success, I will try it later.
>
Hi johannes,

After above change, no error/kernel crash happened while reconfig single 
MLO link which link id is 2.


-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-10-19  4:32                   ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-10-19  4:32 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/18/2022 6:10 PM, Wen Gong wrote:
> On 10/18/2022 5:51 PM, Johannes Berg wrote:
>> On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
>>>> https://p.sipsolutions.net/0652bbbbe350b126.txt
>>> Conflict happened while run "git am" the patch.
>>>
>>> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my
>>> local code,
>>>
>>> also it is missing in
>>> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c 
>>>
>>>
>>> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your
>>> local code?
>>>
>> Ah yes, we didn't upstream that because there's still this discussion
>> about handling puncturing. But you can probably apply around that.
>>
>> johannes
>
> Yes, after apply it.
>
> and apply "commit 3d901102922723eedce6ef10ebd03315a7abb8a5 wifi: 
> mac80211: implement link switching" to
>
> fix build error because my local code is not latest.
>
> it is built success, I will try it later.
>
Hi johannes,

After above change, no error/kernel crash happened while reconfig single 
MLO link which link id is 2.


-- 
ath12k mailing list
ath12k@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/ath12k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
  2022-10-19  4:32                   ` Wen Gong
  (?)
@ 2022-12-15 15:04                     ` Wen Gong
  -1 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-12-15 15:04 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/19/2022 12:32 PM, Wen Gong wrote:
> On 10/18/2022 6:10 PM, Wen Gong wrote:
>> On 10/18/2022 5:51 PM, Johannes Berg wrote:
>>> On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
>>>>> https://p.sipsolutions.net/0652bbbbe350b126.txt
>>>> Conflict happened while run "git am" the patch.
>>>>
>>>> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my
>>>> local code,
>>>>
>>>> also it is missing in
>>>> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c 
>>>>
>>>>
>>>> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your
>>>> local code?
>>>>
>>> Ah yes, we didn't upstream that because there's still this discussion
>>> about handling puncturing. But you can probably apply around that.
>>>
>>> johannes
>>
>> Yes, after apply it.
>>
>> and apply "commit 3d901102922723eedce6ef10ebd03315a7abb8a5 wifi: 
>> mac80211: implement link switching" to
>>
>> fix build error because my local code is not latest.
>>
>> it is built success, I will try it later.
>>
> Hi johannes,
>
> After above change, no error/kernel crash happened while reconfig 
> single MLO link which link id is 2.

Hi Johannes,

I see this patch https://p.sipsolutions.net/0652bbbbe350b126.txt is not 
merged to 
https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c

will your merge it later?



^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-12-15 15:04                     ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-12-15 15:04 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/19/2022 12:32 PM, Wen Gong wrote:
> On 10/18/2022 6:10 PM, Wen Gong wrote:
>> On 10/18/2022 5:51 PM, Johannes Berg wrote:
>>> On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
>>>>> https://p.sipsolutions.net/0652bbbbe350b126.txt
>>>> Conflict happened while run "git am" the patch.
>>>>
>>>> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my
>>>> local code,
>>>>
>>>> also it is missing in
>>>> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c 
>>>>
>>>>
>>>> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your
>>>> local code?
>>>>
>>> Ah yes, we didn't upstream that because there's still this discussion
>>> about handling puncturing. But you can probably apply around that.
>>>
>>> johannes
>>
>> Yes, after apply it.
>>
>> and apply "commit 3d901102922723eedce6ef10ebd03315a7abb8a5 wifi: 
>> mac80211: implement link switching" to
>>
>> fix build error because my local code is not latest.
>>
>> it is built success, I will try it later.
>>
> Hi johannes,
>
> After above change, no error/kernel crash happened while reconfig 
> single MLO link which link id is 2.

Hi Johannes,

I see this patch https://p.sipsolutions.net/0652bbbbe350b126.txt is not 
merged to 
https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c

will your merge it later?



-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/15] mac80211: split bss_info_changed method
@ 2022-12-15 15:04                     ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2022-12-15 15:04 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless; +Cc: ath11k, ath12k

On 10/19/2022 12:32 PM, Wen Gong wrote:
> On 10/18/2022 6:10 PM, Wen Gong wrote:
>> On 10/18/2022 5:51 PM, Johannes Berg wrote:
>>> On Tue, 2022-10-18 at 17:50 +0800, Wen Gong wrote:
>>>>> https://p.sipsolutions.net/0652bbbbe350b126.txt
>>>> Conflict happened while run "git am" the patch.
>>>>
>>>> Because missing the  "changed |= BSS_CHANGED_EHT_PUNCTURING;" in my
>>>> local code,
>>>>
>>>> also it is missing in
>>>> https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c 
>>>>
>>>>
>>>> Maybe "changed |= BSS_CHANGED_EHT_PUNCTURING;" is only existed in your
>>>> local code?
>>>>
>>> Ah yes, we didn't upstream that because there's still this discussion
>>> about handling puncturing. But you can probably apply around that.
>>>
>>> johannes
>>
>> Yes, after apply it.
>>
>> and apply "commit 3d901102922723eedce6ef10ebd03315a7abb8a5 wifi: 
>> mac80211: implement link switching" to
>>
>> fix build error because my local code is not latest.
>>
>> it is built success, I will try it later.
>>
> Hi johannes,
>
> After above change, no error/kernel crash happened while reconfig 
> single MLO link which link id is 2.

Hi Johannes,

I see this patch https://p.sipsolutions.net/0652bbbbe350b126.txt is not 
merged to 
https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git/tree/net/mac80211/util.c

will your merge it later?



-- 
ath12k mailing list
ath12k@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/ath12k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/15] mac80211: make channel context code MLO-aware
  2022-06-01  7:39 ` [PATCH 04/15] mac80211: make channel context code MLO-aware Johannes Berg
@ 2023-02-14  7:57     ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2023-02-14  7:57 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless, ath11k; +Cc: Johannes Berg

On 6/1/2022 3:39 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Make the channel context code MLO aware, along with some
> functions that it uses, so that the chan.c file is now
> MLD-clean and no longer uses deflink/bss_conf/etc.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
...
> diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
> index f22381127948..b268088585eb 100644
> --- a/net/mac80211/rate.c
> +++ b/net/mac80211/rate.c
> @@ -90,14 +90,17 @@ void rate_control_tx_status(struct ieee80211_local *local,
>   }
>   
>   void rate_control_rate_update(struct ieee80211_local *local,
> -				    struct ieee80211_supported_band *sband,
> -				    struct sta_info *sta, u32 changed)
> +			      struct ieee80211_supported_band *sband,
> +			      struct sta_info *sta, unsigned int link_id,
> +			      u32 changed)
>   {
>   	struct rate_control_ref *ref = local->rate_ctrl;
>   	struct ieee80211_sta *ista = &sta->sta;
>   	void *priv_sta = sta->rate_ctrl_priv;
>   	struct ieee80211_chanctx_conf *chanctx_conf;
>   
> +	WARN_ON(link_id != 0);
> +
>   	if (ref && ref->ops->rate_update) {
>   		rcu_read_lock();
>   

Why link_id must = 0 here?

Now I hit a warning here.

[421752.744684] wlan0: [link 1] AP 02:03:7f:01:52:26 changed bandwidth, 
new config is 6435.000 MHz, width 1 (6435.000/0 MHz)
[421752.744760] ------------[ cut here ]------------
[421752.744762] WARNING: CPU: 4 PID: 3844301 at net/mac80211/rate.c:104 
rate_control_rate_update+0xe2/0x100 [mac80211]
[421752.744833] Modules linked in: tls cpuid rfcomm ccm michael_mic cmac 
algif_hash algif_skcipher af_alg qrtr_mhi bnep intel_rapl_msr 
intel_rapl_common snd_hda_codec_realtek snd_hda_codec_generic 
ledtrig_audio edac_mce_amd snd_hda_codec_hdmi snd_hda_intel 
snd_intel_dspcfg qrtr snd_hda_codec kvm_amd snd_hda_core binfmt_misc 
ath12k snd_hwdep kvm snd_pcm mhi irqbypass qmi_helpers nls_iso8859_1 
snd_seq_midi crct10dif_pclmul btusb snd_seq_midi_event 
ghash_clmulni_intel mac80211 snd_rawmidi btrtl aesni_intel crypto_simd 
snd_seq cryptd btbcm btintel snd_seq_device rapl input_leds bluetooth 
joydev wmi_bmof serio_raw snd_timer cfg80211 k10temp ecdh_generic ecc 
snd libarc4 ccp soundcore ucsi_acpi typec_ucsi typec mac_hid cm32181 
industrialio sch_fq_codel msr parport_pc ppdev lp parport ramoops 
reed_solomon drm efi_pstore ip_tables x_tables autofs4 ax88179_178a 
usbnet mii hid_generic usbhid hid crc32_pclmul nvme ahci i2c_piix4 
libahci nvme_core wmi video
[421752.744982] CPU: 4 PID: 3844301 Comm: kworker/u32:2 Kdump: loaded 
Tainted: G        W          6.0.0-rc2+ #3
[421752.744989] Hardware name: AMD Celadon-RN/Celadon-RN, BIOS RCD0080A 
09/04/2019
[421752.744993] Workqueue: phy0 ieee80211_iface_work [mac80211]
[421752.745048] RIP: 0010:rate_control_rate_update+0xe2/0x100 [mac80211]
[421752.745100] Code: e8 f3 a3 33 d0 48 8b 73 50 44 89 f1 4c 89 ea 4c 89 
ff e8 71 16 fe ff 48 83 c4 20 5b 41 5c 41 5d 41 5e 41 5f 5d e9 de 24 20 
d1 <0f> 0b e9 4c ff ff ff 0f 0b e8 c0 a3 33 d0 eb dd 0f 1f 40 00 66 2e
[421752.745104] RSP: 0018:ffffadc0911efab0 EFLAGS: 00010202
[421752.745109] RAX: 0000000000000000 RBX: ffff9e8619b20000 RCX: 
0000000000000001
[421752.745112] RDX: ffff9e8619b20000 RSI: ffff9e8412ac3610 RDI: 
ffff9e8412ac08e0
[421752.745115] RBP: ffffadc0911efaf8 R08: 0000000000000001 R09: 
c000000100b1fe35
[421752.745117] R10: ffff9e8412ac04f0 R11: ffffadc0911ef9c0 R12: 
0000000000000000
[421752.745120] R13: ffff9e8619b20ab0 R14: 0000000000000001 R15: 
ffff9e8412ac08e0
[421752.745123] FS:  0000000000000000(0000) GS:ffff9e86ff700000(0000) 
knlGS:0000000000000000
[421752.745127] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[421752.745130] CR2: 00007f03cdb34538 CR3: 00000002f020a000 CR4: 
0000000000350ee0
[421752.745133] Call Trace:
[421752.745137]  <TASK>
[421752.745147]  ieee80211_chan_bw_change+0x100/0x130 [mac80211]
[421752.745213]  ieee80211_change_chanctx+0x51/0x2a0 [mac80211]
[421752.745263]  ieee80211_recalc_chanctx_chantype+0x133/0x180 [mac80211]
[421752.745287]  ieee80211_link_change_bandwidth+0xf5/0x180 [mac80211]
[421752.745306]  ieee80211_rx_mgmt_beacon+0xc82/0x1b30 [mac80211]
[421752.745333]  ? update_load_avg+0x224/0x770
[421752.745338]  ? update_load_avg+0x224/0x770
[421752.745339]  ? native_send_call_func_single_ipi+0x1e/0x30
[421752.745344]  ieee80211_sta_rx_queued_mgmt+0x173/0xad0 [mac80211]
[421752.745364]  ? newidle_balance+0x256/0x410
[421752.745367]  ? preempt_count_add+0x7c/0xc0
[421752.745370]  ? _raw_spin_lock_irqsave+0x28/0x60
[421752.745375]  ieee80211_iface_work+0x2fc/0x400 [mac80211]
[421752.745395]  process_one_work+0x227/0x440
[421752.745398]  worker_thread+0x31/0x3e0
[421752.745400]  ? process_one_work+0x440/0x440
[421752.745402]  kthread+0xfe/0x130
[421752.745404]  ? kthread_complete_and_exit+0x20/0x20
[421752.745407]  ret_from_fork+0x22/0x30
[421752.745412]  </TASK>
[421752.745412] ---[ end trace 0000000000000000 ]---

...

>   

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/15] mac80211: make channel context code MLO-aware
@ 2023-02-14  7:57     ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2023-02-14  7:57 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless, ath11k; +Cc: Johannes Berg

On 6/1/2022 3:39 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Make the channel context code MLO aware, along with some
> functions that it uses, so that the chan.c file is now
> MLD-clean and no longer uses deflink/bss_conf/etc.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
...
> diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
> index f22381127948..b268088585eb 100644
> --- a/net/mac80211/rate.c
> +++ b/net/mac80211/rate.c
> @@ -90,14 +90,17 @@ void rate_control_tx_status(struct ieee80211_local *local,
>   }
>   
>   void rate_control_rate_update(struct ieee80211_local *local,
> -				    struct ieee80211_supported_band *sband,
> -				    struct sta_info *sta, u32 changed)
> +			      struct ieee80211_supported_band *sband,
> +			      struct sta_info *sta, unsigned int link_id,
> +			      u32 changed)
>   {
>   	struct rate_control_ref *ref = local->rate_ctrl;
>   	struct ieee80211_sta *ista = &sta->sta;
>   	void *priv_sta = sta->rate_ctrl_priv;
>   	struct ieee80211_chanctx_conf *chanctx_conf;
>   
> +	WARN_ON(link_id != 0);
> +
>   	if (ref && ref->ops->rate_update) {
>   		rcu_read_lock();
>   

Why link_id must = 0 here?

Now I hit a warning here.

[421752.744684] wlan0: [link 1] AP 02:03:7f:01:52:26 changed bandwidth, 
new config is 6435.000 MHz, width 1 (6435.000/0 MHz)
[421752.744760] ------------[ cut here ]------------
[421752.744762] WARNING: CPU: 4 PID: 3844301 at net/mac80211/rate.c:104 
rate_control_rate_update+0xe2/0x100 [mac80211]
[421752.744833] Modules linked in: tls cpuid rfcomm ccm michael_mic cmac 
algif_hash algif_skcipher af_alg qrtr_mhi bnep intel_rapl_msr 
intel_rapl_common snd_hda_codec_realtek snd_hda_codec_generic 
ledtrig_audio edac_mce_amd snd_hda_codec_hdmi snd_hda_intel 
snd_intel_dspcfg qrtr snd_hda_codec kvm_amd snd_hda_core binfmt_misc 
ath12k snd_hwdep kvm snd_pcm mhi irqbypass qmi_helpers nls_iso8859_1 
snd_seq_midi crct10dif_pclmul btusb snd_seq_midi_event 
ghash_clmulni_intel mac80211 snd_rawmidi btrtl aesni_intel crypto_simd 
snd_seq cryptd btbcm btintel snd_seq_device rapl input_leds bluetooth 
joydev wmi_bmof serio_raw snd_timer cfg80211 k10temp ecdh_generic ecc 
snd libarc4 ccp soundcore ucsi_acpi typec_ucsi typec mac_hid cm32181 
industrialio sch_fq_codel msr parport_pc ppdev lp parport ramoops 
reed_solomon drm efi_pstore ip_tables x_tables autofs4 ax88179_178a 
usbnet mii hid_generic usbhid hid crc32_pclmul nvme ahci i2c_piix4 
libahci nvme_core wmi video
[421752.744982] CPU: 4 PID: 3844301 Comm: kworker/u32:2 Kdump: loaded 
Tainted: G        W          6.0.0-rc2+ #3
[421752.744989] Hardware name: AMD Celadon-RN/Celadon-RN, BIOS RCD0080A 
09/04/2019
[421752.744993] Workqueue: phy0 ieee80211_iface_work [mac80211]
[421752.745048] RIP: 0010:rate_control_rate_update+0xe2/0x100 [mac80211]
[421752.745100] Code: e8 f3 a3 33 d0 48 8b 73 50 44 89 f1 4c 89 ea 4c 89 
ff e8 71 16 fe ff 48 83 c4 20 5b 41 5c 41 5d 41 5e 41 5f 5d e9 de 24 20 
d1 <0f> 0b e9 4c ff ff ff 0f 0b e8 c0 a3 33 d0 eb dd 0f 1f 40 00 66 2e
[421752.745104] RSP: 0018:ffffadc0911efab0 EFLAGS: 00010202
[421752.745109] RAX: 0000000000000000 RBX: ffff9e8619b20000 RCX: 
0000000000000001
[421752.745112] RDX: ffff9e8619b20000 RSI: ffff9e8412ac3610 RDI: 
ffff9e8412ac08e0
[421752.745115] RBP: ffffadc0911efaf8 R08: 0000000000000001 R09: 
c000000100b1fe35
[421752.745117] R10: ffff9e8412ac04f0 R11: ffffadc0911ef9c0 R12: 
0000000000000000
[421752.745120] R13: ffff9e8619b20ab0 R14: 0000000000000001 R15: 
ffff9e8412ac08e0
[421752.745123] FS:  0000000000000000(0000) GS:ffff9e86ff700000(0000) 
knlGS:0000000000000000
[421752.745127] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[421752.745130] CR2: 00007f03cdb34538 CR3: 00000002f020a000 CR4: 
0000000000350ee0
[421752.745133] Call Trace:
[421752.745137]  <TASK>
[421752.745147]  ieee80211_chan_bw_change+0x100/0x130 [mac80211]
[421752.745213]  ieee80211_change_chanctx+0x51/0x2a0 [mac80211]
[421752.745263]  ieee80211_recalc_chanctx_chantype+0x133/0x180 [mac80211]
[421752.745287]  ieee80211_link_change_bandwidth+0xf5/0x180 [mac80211]
[421752.745306]  ieee80211_rx_mgmt_beacon+0xc82/0x1b30 [mac80211]
[421752.745333]  ? update_load_avg+0x224/0x770
[421752.745338]  ? update_load_avg+0x224/0x770
[421752.745339]  ? native_send_call_func_single_ipi+0x1e/0x30
[421752.745344]  ieee80211_sta_rx_queued_mgmt+0x173/0xad0 [mac80211]
[421752.745364]  ? newidle_balance+0x256/0x410
[421752.745367]  ? preempt_count_add+0x7c/0xc0
[421752.745370]  ? _raw_spin_lock_irqsave+0x28/0x60
[421752.745375]  ieee80211_iface_work+0x2fc/0x400 [mac80211]
[421752.745395]  process_one_work+0x227/0x440
[421752.745398]  worker_thread+0x31/0x3e0
[421752.745400]  ? process_one_work+0x440/0x440
[421752.745402]  kthread+0xfe/0x130
[421752.745404]  ? kthread_complete_and_exit+0x20/0x20
[421752.745407]  ret_from_fork+0x22/0x30
[421752.745412]  </TASK>
[421752.745412] ---[ end trace 0000000000000000 ]---

...

>   

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/15] mac80211: make channel context code MLO-aware
  2023-02-14  7:57     ` Wen Gong
@ 2023-02-14  8:04       ` Johannes Berg
  -1 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2023-02-14  8:04 UTC (permalink / raw)
  To: Wen Gong, linux-wireless, ath11k

On Tue, 2023-02-14 at 15:57 +0800, Wen Gong wrote:
> 
> >   void rate_control_rate_update(struct ieee80211_local *local,
> > -				    struct ieee80211_supported_band *sband,
> > -				    struct sta_info *sta, u32 changed)
> > +			      struct ieee80211_supported_band *sband,
> > +			      struct sta_info *sta, unsigned int link_id,
> > +			      u32 changed)
> >   {
> >   	struct rate_control_ref *ref = local->rate_ctrl;
> >   	struct ieee80211_sta *ista = &sta->sta;
> >   	void *priv_sta = sta->rate_ctrl_priv;
> >   	struct ieee80211_chanctx_conf *chanctx_conf;
> >   
> > +	WARN_ON(link_id != 0);
> > +
> >   	if (ref && ref->ops->rate_update) {
> >   		rcu_read_lock();
> >   
> 
> Why link_id must = 0 here?
> 

The whole software rate scaling hasn't been adjusted for MLO yet.

johannes

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/15] mac80211: make channel context code MLO-aware
@ 2023-02-14  8:04       ` Johannes Berg
  0 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2023-02-14  8:04 UTC (permalink / raw)
  To: Wen Gong, linux-wireless, ath11k

On Tue, 2023-02-14 at 15:57 +0800, Wen Gong wrote:
> 
> >   void rate_control_rate_update(struct ieee80211_local *local,
> > -				    struct ieee80211_supported_band *sband,
> > -				    struct sta_info *sta, u32 changed)
> > +			      struct ieee80211_supported_band *sband,
> > +			      struct sta_info *sta, unsigned int link_id,
> > +			      u32 changed)
> >   {
> >   	struct rate_control_ref *ref = local->rate_ctrl;
> >   	struct ieee80211_sta *ista = &sta->sta;
> >   	void *priv_sta = sta->rate_ctrl_priv;
> >   	struct ieee80211_chanctx_conf *chanctx_conf;
> >   
> > +	WARN_ON(link_id != 0);
> > +
> >   	if (ref && ref->ops->rate_update) {
> >   		rcu_read_lock();
> >   
> 
> Why link_id must = 0 here?
> 

The whole software rate scaling hasn't been adjusted for MLO yet.

johannes

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/15] mac80211: make channel context code MLO-aware
  2023-02-14  8:04       ` Johannes Berg
@ 2023-02-14  8:09         ` Wen Gong
  -1 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2023-02-14  8:09 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless, ath11k

On 2/14/2023 4:04 PM, Johannes Berg wrote:
> On Tue, 2023-02-14 at 15:57 +0800, Wen Gong wrote:
>>>    void rate_control_rate_update(struct ieee80211_local *local,
>>> -				    struct ieee80211_supported_band *sband,
>>> -				    struct sta_info *sta, u32 changed)
>>> +			      struct ieee80211_supported_band *sband,
>>> +			      struct sta_info *sta, unsigned int link_id,
>>> +			      u32 changed)
>>>    {
>>>    	struct rate_control_ref *ref = local->rate_ctrl;
>>>    	struct ieee80211_sta *ista = &sta->sta;
>>>    	void *priv_sta = sta->rate_ctrl_priv;
>>>    	struct ieee80211_chanctx_conf *chanctx_conf;
>>>    
>>> +	WARN_ON(link_id != 0);
>>> +
>>>    	if (ref && ref->ops->rate_update) {
>>>    		rcu_read_lock();
>>>    
>> Why link_id must = 0 here?
>>
> The whole software rate scaling hasn't been adjusted for MLO yet.

Got it. Thanks.

So I guess this WARN_ON will be change later.

>
> johannes

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/15] mac80211: make channel context code MLO-aware
@ 2023-02-14  8:09         ` Wen Gong
  0 siblings, 0 replies; 53+ messages in thread
From: Wen Gong @ 2023-02-14  8:09 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless, ath11k

On 2/14/2023 4:04 PM, Johannes Berg wrote:
> On Tue, 2023-02-14 at 15:57 +0800, Wen Gong wrote:
>>>    void rate_control_rate_update(struct ieee80211_local *local,
>>> -				    struct ieee80211_supported_band *sband,
>>> -				    struct sta_info *sta, u32 changed)
>>> +			      struct ieee80211_supported_band *sband,
>>> +			      struct sta_info *sta, unsigned int link_id,
>>> +			      u32 changed)
>>>    {
>>>    	struct rate_control_ref *ref = local->rate_ctrl;
>>>    	struct ieee80211_sta *ista = &sta->sta;
>>>    	void *priv_sta = sta->rate_ctrl_priv;
>>>    	struct ieee80211_chanctx_conf *chanctx_conf;
>>>    
>>> +	WARN_ON(link_id != 0);
>>> +
>>>    	if (ref && ref->ops->rate_update) {
>>>    		rcu_read_lock();
>>>    
>> Why link_id must = 0 here?
>>
> The whole software rate scaling hasn't been adjusted for MLO yet.

Got it. Thanks.

So I guess this WARN_ON will be change later.

>
> johannes

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/15] mac80211: make channel context code MLO-aware
  2023-02-14  8:09         ` Wen Gong
@ 2023-02-14  8:13           ` Johannes Berg
  -1 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2023-02-14  8:13 UTC (permalink / raw)
  To: Wen Gong, linux-wireless, ath11k

On Tue, 2023-02-14 at 16:09 +0800, Wen Gong wrote:
> On 2/14/2023 4:04 PM, Johannes Berg wrote:
> > On Tue, 2023-02-14 at 15:57 +0800, Wen Gong wrote:
> > > >    void rate_control_rate_update(struct ieee80211_local *local,
> > > > -				    struct ieee80211_supported_band *sband,
> > > > -				    struct sta_info *sta, u32 changed)
> > > > +			      struct ieee80211_supported_band *sband,
> > > > +			      struct sta_info *sta, unsigned int link_id,
> > > > +			      u32 changed)
> > > >    {
> > > >    	struct rate_control_ref *ref = local->rate_ctrl;
> > > >    	struct ieee80211_sta *ista = &sta->sta;
> > > >    	void *priv_sta = sta->rate_ctrl_priv;
> > > >    	struct ieee80211_chanctx_conf *chanctx_conf;
> > > >    
> > > > +	WARN_ON(link_id != 0);
> > > > +
> > > >    	if (ref && ref->ops->rate_update) {
> > > >    		rcu_read_lock();
> > > >    
> > > Why link_id must = 0 here?
> > > 
> > The whole software rate scaling hasn't been adjusted for MLO yet.
> 
> Got it. Thanks.
> 
> So I guess this WARN_ON will be change later.
> 

Since you're running into it, you should probably think about addressing
this ... I'm not going to, our hardware doesn't use this code.

johannes

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/15] mac80211: make channel context code MLO-aware
@ 2023-02-14  8:13           ` Johannes Berg
  0 siblings, 0 replies; 53+ messages in thread
From: Johannes Berg @ 2023-02-14  8:13 UTC (permalink / raw)
  To: Wen Gong, linux-wireless, ath11k

On Tue, 2023-02-14 at 16:09 +0800, Wen Gong wrote:
> On 2/14/2023 4:04 PM, Johannes Berg wrote:
> > On Tue, 2023-02-14 at 15:57 +0800, Wen Gong wrote:
> > > >    void rate_control_rate_update(struct ieee80211_local *local,
> > > > -				    struct ieee80211_supported_band *sband,
> > > > -				    struct sta_info *sta, u32 changed)
> > > > +			      struct ieee80211_supported_band *sband,
> > > > +			      struct sta_info *sta, unsigned int link_id,
> > > > +			      u32 changed)
> > > >    {
> > > >    	struct rate_control_ref *ref = local->rate_ctrl;
> > > >    	struct ieee80211_sta *ista = &sta->sta;
> > > >    	void *priv_sta = sta->rate_ctrl_priv;
> > > >    	struct ieee80211_chanctx_conf *chanctx_conf;
> > > >    
> > > > +	WARN_ON(link_id != 0);
> > > > +
> > > >    	if (ref && ref->ops->rate_update) {
> > > >    		rcu_read_lock();
> > > >    
> > > Why link_id must = 0 here?
> > > 
> > The whole software rate scaling hasn't been adjusted for MLO yet.
> 
> Got it. Thanks.
> 
> So I guess this WARN_ON will be change later.
> 

Since you're running into it, you should probably think about addressing
this ... I'm not going to, our hardware doesn't use this code.

johannes

^ permalink raw reply	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2023-02-14  8:14 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-01  7:39 [PATCH 00/15] mac80211 MLO updates Johannes Berg
2022-06-01  7:39 ` [PATCH 01/15] mac80211: split bss_info_changed method Johannes Berg
2022-06-01 19:31   ` Jeff Johnson
2022-06-01 19:39     ` Johannes Berg
2022-10-18  8:47   ` Wen Gong
2022-10-18  8:47     ` Wen Gong
2022-10-18  8:47     ` Wen Gong
2022-10-18  8:50     ` Johannes Berg
2022-10-18  8:50       ` Johannes Berg
2022-10-18  8:50       ` Johannes Berg
2022-10-18  8:52       ` Wen Gong
2022-10-18  8:52         ` Wen Gong
2022-10-18  8:52         ` Wen Gong
2022-10-18  8:53         ` Johannes Berg
2022-10-18  8:53           ` Johannes Berg
2022-10-18  8:53           ` Johannes Berg
2022-10-18  9:50           ` Wen Gong
2022-10-18  9:50             ` Wen Gong
2022-10-18  9:50             ` Wen Gong
2022-10-18  9:51             ` Johannes Berg
2022-10-18  9:51               ` Johannes Berg
2022-10-18  9:51               ` Johannes Berg
2022-10-18 10:10               ` Wen Gong
2022-10-18 10:10                 ` Wen Gong
2022-10-18 10:10                 ` Wen Gong
2022-10-19  4:32                 ` Wen Gong
2022-10-19  4:32                   ` Wen Gong
2022-10-19  4:32                   ` Wen Gong
2022-12-15 15:04                   ` Wen Gong
2022-12-15 15:04                     ` Wen Gong
2022-12-15 15:04                     ` Wen Gong
2022-06-01  7:39 ` [PATCH 02/15] mac80211: add per-link configuration pointer Johannes Berg
2022-06-01  7:39 ` [PATCH 03/15] mac80211: pass link ID where already present Johannes Berg
2022-06-01  7:39 ` [PATCH 04/15] mac80211: make channel context code MLO-aware Johannes Berg
2023-02-14  7:57   ` Wen Gong
2023-02-14  7:57     ` Wen Gong
2023-02-14  8:04     ` Johannes Berg
2023-02-14  8:04       ` Johannes Berg
2023-02-14  8:09       ` Wen Gong
2023-02-14  8:09         ` Wen Gong
2023-02-14  8:13         ` Johannes Berg
2023-02-14  8:13           ` Johannes Berg
2022-06-01  7:39 ` [PATCH 05/15] mac80211: remove sta_info_tx_streams() Johannes Berg
2022-06-01  7:39 ` [PATCH 06/15] mac80211: refactor some sta_info link handling Johannes Berg
2022-06-01  7:39 ` [PATCH 07/15] mac80211: use IEEE80211_MLD_MAX_NUM_LINKS Johannes Berg
2022-06-01  7:39 ` [PATCH 08/15] mac80211: validate some driver features for MLO Johannes Berg
2022-06-01  7:39 ` [PATCH 09/15] mac80211: refactor some link setup code Johannes Berg
2022-06-01  7:39 ` [PATCH 10/15] mac80211: add link_id to vht.c code for MLO Johannes Berg
2022-06-01  7:39 ` [PATCH 11/15] mac80211: add link_id to eht.c " Johannes Berg
2022-06-01  7:39 ` [PATCH 12/15] mac80211: HT: make ieee80211_ht_cap_ie_to_sta_ht_cap() MLO-aware Johannes Berg
2022-06-01  7:39 ` [PATCH 13/15] mac80211: make some SMPS code MLD-aware Johannes Berg
2022-06-01  7:39 ` [PATCH 14/15] mac80211: make ieee80211_he_cap_ie_to_sta_he_cap() MLO-aware Johannes Berg
2022-06-01  7:39 ` [PATCH 15/15] mac80211: correct link config data in tracing Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.