summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorBaochen Qiang <baochen.qiang@oss.qualcomm.com>2026-07-20 14:43:24 +0800
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>2026-07-27 08:00:42 -0700
commitdd121ed779dd62c7679815f7c5a0b07da60a39bf (patch)
treeec091b631e3cc15c31edf041b4ad59d8c0c16776 /drivers/net/wireless
parent21ca38bb6b53a0b610998f370a91e656dc9e0542 (diff)
wifi: ath12k: keep ATH12K_PEER_ML_ID_VALID set in ath12k_sta::ml_peer_id
Several pieces of host bookkeeping for MLD peer IDs encode the same fact in different ways: - ath12k_sta::ml_peer_id stores the raw ID in [0, ATH12K_MAX_MLO_PEERS); - ath12k_dp_peer::peer_id, ath12k_dp_link_peer::ml_id and the index used on ath12k_dp_hw::dp_peers[] always carry the ATH12K_PEER_ML_ID_VALID bit (BIT(13)) when the ID is real; - WMI_MLO_PEER_ASSOC_PARAMS::ml_peer_id sent down to firmware is raw, without the bookkeeping bit. The mismatch leaks into call sites that have to remember to OR the bit in (ath12k_peer_create(), ath12k_mac_op_sta_state()) or remember not to (ath12k_peer_assoc_h_mlo()). Make ath12k_sta::ml_peer_id carry the VALID bit when valid, the same way ath12k_dp_peer::peer_id and ath12k_dp_link_peer::ml_id do: - ath12k_peer_ml_alloc() OR-s the bit in once on the way out; the internal bitmap stays raw [0, ATH12K_MAX_MLO_PEERS); - ath12k_peer_create() and ath12k_mac_op_sta_state() drop the explicit OR; - ath12k_peer_assoc_h_mlo() masks the bit off when populating the WMI ml_peer_id; While there, introduce ath12k_peer_ml_free() to mirror ath12k_peer_ml_alloc(), which helps avoid code duplication. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com> Link: https://patch.msgid.link/20260720-ath12k-fw-allocated-ml-peer-id-v2-3-630632758a80@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c27
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.c17
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.h1
3 files changed, 28 insertions, 17 deletions
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index b4df222f0c19..06f1a1ba994a 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -1282,16 +1282,15 @@ void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah)
struct ath12k_dp_peer *dp_peer, *tmp;
struct ath12k_dp_hw *dp_hw = &ah->dp_hw;
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
INIT_LIST_HEAD(&peers);
spin_lock_bh(&dp_hw->peer_lock);
list_for_each_entry_safe(dp_peer, tmp, &dp_hw->dp_peers_list, list) {
if (dp_peer->is_mlo) {
- struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(dp_peer->sta);
-
rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
- clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
- ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
+ ath12k_peer_ml_free(ah, ath12k_sta_to_ahsta(dp_peer->sta));
}
list_move(&dp_peer->list, &peers);
@@ -3551,7 +3550,11 @@ static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,
ether_addr_copy(ml->mld_addr, sta->addr);
ml->logical_link_idx = arsta->link_idx;
- ml->ml_peer_id = ahsta->ml_peer_id;
+ /*
+ * WMI_MLO_PEER_ASSOC_PARAMS expects the raw ML peer ID without
+ * the host-side ATH12K_PEER_ML_ID_VALID bookkeeping bit.
+ */
+ ml->ml_peer_id = ahsta->ml_peer_id & ~ATH12K_PEER_ML_ID_VALID;
ml->ieee_link_id = arsta->link_id;
ml->num_partner_links = 0;
ml->eml_cap = sta->eml_cap;
@@ -7268,10 +7271,8 @@ static void ath12k_mac_ml_station_remove(struct ath12k_vif *ahvif,
ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id);
}
- if (sta->mlo) {
- clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
- ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
- }
+ if (sta->mlo)
+ ath12k_peer_ml_free(ah, ahsta);
}
static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
@@ -7743,7 +7744,7 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
}
dp_params.is_mlo = true;
- dp_params.peer_id = ahsta->ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+ dp_params.peer_id = ahsta->ml_peer_id;
}
dp_params.sta = sta;
@@ -7880,10 +7881,8 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
peer_delete:
ath12k_dp_peer_delete(&ah->dp_hw, sta->addr, sta);
ml_peer_id_clear:
- if (sta->mlo) {
- clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
- ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
- }
+ if (sta->mlo)
+ ath12k_peer_ml_free(ah, ahsta);
exit:
/* update the state if everything went well */
if (!ret)
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index 2681a047d4d5..5dd7c6470219 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -230,7 +230,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
/* Fill ML info into created peer */
if (sta->mlo) {
ml_peer_id = ahsta->ml_peer_id;
- peer->ml_id = ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+ peer->ml_id = ml_peer_id;
ether_addr_copy(peer->ml_addr, sta->addr);
/* the assoc link is considered primary for now */
@@ -276,9 +276,20 @@ u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah)
}
if (ml_peer_id == ATH12K_MAX_MLO_PEERS)
- ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
+ return ATH12K_MLO_PEER_ID_INVALID;
- return ml_peer_id;
+ return ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+}
+
+void ath12k_peer_ml_free(struct ath12k_hw *ah, struct ath12k_sta *ahsta)
+{
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ if (ahsta->ml_peer_id <
+ (ATH12K_MAX_MLO_PEERS | ATH12K_PEER_ML_ID_VALID))
+ clear_bit(ahsta->ml_peer_id & ~ATH12K_PEER_ML_ID_VALID,
+ ah->free_ml_peer_id_map);
+ ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
}
int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta)
diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
index 49d89796bc46..0f7f25b8e89c 100644
--- a/drivers/net/wireless/ath/ath12k/peer.h
+++ b/drivers/net/wireless/ath/ath12k/peer.h
@@ -26,4 +26,5 @@ int ath12k_link_sta_rhash_add(struct ath12k_base *ab, struct ath12k_link_sta *ar
struct ath12k_link_sta *ath12k_link_sta_find_by_addr(struct ath12k_base *ab,
const u8 *addr);
u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah);
+void ath12k_peer_ml_free(struct ath12k_hw *ah, struct ath12k_sta *ahsta);
#endif /* _PEER_H_ */