mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 20:30:26 -04:00
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>
This commit is contained in:
committed by
Jeff Johnson
parent
21ca38bb6b
commit
dd121ed779
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
Reference in New Issue
Block a user