diff options
| author | Baochen Qiang <baochen.qiang@oss.qualcomm.com> | 2026-07-20 14:43:24 +0800 |
|---|---|---|
| committer | Jeff Johnson <jeff.johnson@oss.qualcomm.com> | 2026-07-27 08:00:42 -0700 |
| commit | dd121ed779dd62c7679815f7c5a0b07da60a39bf (patch) | |
| tree | ec091b631e3cc15c31edf041b4ad59d8c0c16776 /drivers/net/wireless | |
| parent | 21ca38bb6b53a0b610998f370a91e656dc9e0542 (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.c | 27 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/peer.c | 17 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/peer.h | 1 |
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_ */ |
