mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
wifi: ath12k: defer dp_peer registration when firmware allocates MLD peer ID
For chips with host_alloc_ml_id=true (QCN9274 etc.), the host allocates
the MLD peer ID up front; ath12k_dp_peer_create() publishes the dp_peer
into dp_hw->dp_peers[] using that ID immediately. WCN7850/QCC2072 does
not work that way: the firmware picks the ID and only tells the host
afterwards via HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP, so the publication has
to be delayed until the event arrives.
Introduce ATH12K_MLO_PEER_ID_PENDING (0xFFFE) as a sentinel for "is_mlo,
but ID not yet known". On the firmware-allocates path:
- ath12k_mac_op_sta_state(NOTEXIST->NONE) skips ath12k_peer_ml_alloc()
and stores PENDING in ahsta->ml_peer_id and dp_params.peer_id;
- ath12k_dp_peer_create() skips dp_peer registration until a real ID is
known;
- ath12k_peer_create() leaves peer->ml_id at INVALID so consumer sites
do not treat PENDING as a real ID;
- ath12k_peer_ml_free() and ath12k_mac_dp_peer_cleanup() skip the
dp_peers[] write and the free_ml_peer_id_map clear when
host_alloc_ml_id is false or the ID is still PENDING.
The HTT handler change that resolves the PENDING ID is added in a
follow-up patch.
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-7-630632758a80@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
parent
1726a7a10c
commit
a7619b3bcb
|
|
@ -72,6 +72,7 @@
|
|||
|
||||
#define ATH12K_MAX_MLO_PEERS 256
|
||||
#define ATH12K_MLO_PEER_ID_INVALID 0xFFFF
|
||||
#define ATH12K_MLO_PEER_ID_PENDING 0xFFFE
|
||||
|
||||
#define ATH12K_INVALID_RSSI_FULL -1
|
||||
#define ATH12K_INVALID_RSSI_EMPTY -128
|
||||
|
|
|
|||
|
|
@ -475,7 +475,9 @@ int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,
|
|||
dp_peer->is_mlo = params->is_mlo;
|
||||
|
||||
/*
|
||||
* For MLO client, the host assigns the ML peer ID, so set peer_id in dp_peer
|
||||
* For MLO client, the ML peer ID, either known or PENDING, needs to be
|
||||
* initialized here since the following logic depends on it.
|
||||
*
|
||||
* For non-MLO client, host gets link peer ID from firmware and will be
|
||||
* assigned at the time of link peer creation
|
||||
*/
|
||||
|
|
@ -491,13 +493,17 @@ int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,
|
|||
list_add(&dp_peer->list, &dp_hw->dp_peers_list);
|
||||
|
||||
/*
|
||||
* For MLO client, the peer_id for ath12k_dp_peer is allocated by host
|
||||
* and that peer_id is known at this point, and hence this ath12k_dp_peer
|
||||
* can be added to the RCU table using the peer_id.
|
||||
* For non-MLO client, this addition to RCU table shall be done at the
|
||||
* time of assignment of ath12k_dp_link_peer to ath12k_dp_peer.
|
||||
* For an MLO client whose ML peer ID is allocated by the host, the
|
||||
* peer_id is known here and the dp_peer can be added to the RCU
|
||||
* table using it. For an MLO client on chips where the firmware
|
||||
* allocates the ID, peer_id is ATH12K_MLO_PEER_ID_PENDING and the
|
||||
* RCU table publish is deferred to the
|
||||
* HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP handler. For a non-MLO client
|
||||
* the publish happens later, at the time of assignment of
|
||||
* ath12k_dp_link_peer to ath12k_dp_peer.
|
||||
*/
|
||||
if (dp_peer->is_mlo)
|
||||
if (dp_peer->is_mlo &&
|
||||
dp_peer->peer_id != ATH12K_MLO_PEER_ID_PENDING)
|
||||
rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], dp_peer);
|
||||
|
||||
spin_unlock_bh(&dp_hw->peer_lock);
|
||||
|
|
@ -518,7 +524,8 @@ void ath12k_dp_peer_delete(struct ath12k_dp_hw *dp_hw, u8 *addr,
|
|||
return;
|
||||
}
|
||||
|
||||
if (dp_peer->is_mlo)
|
||||
if (dp_peer->is_mlo &&
|
||||
dp_peer->peer_id != ATH12K_MLO_PEER_ID_PENDING)
|
||||
rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
|
||||
|
||||
list_del(&dp_peer->list);
|
||||
|
|
|
|||
|
|
@ -1289,7 +1289,9 @@ void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah)
|
|||
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) {
|
||||
rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
|
||||
if (dp_peer->peer_id != ATH12K_MLO_PEER_ID_PENDING)
|
||||
rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id],
|
||||
NULL);
|
||||
ath12k_peer_ml_free(ah, ath12k_sta_to_ahsta(dp_peer->sta));
|
||||
}
|
||||
|
||||
|
|
@ -7750,11 +7752,19 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
|
|||
/* ML sta */
|
||||
if (sta->mlo && !ahsta->links_map &&
|
||||
(hweight16(sta->valid_links) == 1)) {
|
||||
ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah);
|
||||
if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
|
||||
ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM",
|
||||
sta->addr);
|
||||
goto exit;
|
||||
if (ah->host_alloc_ml_id) {
|
||||
ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah);
|
||||
if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
|
||||
ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM",
|
||||
sta->addr);
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* firmware allocates the ML peer ID and notifies
|
||||
* the host via HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP
|
||||
*/
|
||||
ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_PENDING;
|
||||
}
|
||||
|
||||
dp_params.is_mlo = true;
|
||||
|
|
|
|||
|
|
@ -230,7 +230,16 @@ 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;
|
||||
/*
|
||||
* For chips where firmware allocates the ML peer ID,
|
||||
* ml_peer_id is ATH12K_MLO_PEER_ID_PENDING here. The
|
||||
* MLO_RX_PEER_MAP HTT event handler fixes up
|
||||
* peer->ml_id once the ID is known.
|
||||
*/
|
||||
if (ml_peer_id == ATH12K_MLO_PEER_ID_PENDING)
|
||||
peer->ml_id = ATH12K_MLO_PEER_ID_INVALID;
|
||||
else
|
||||
peer->ml_id = ml_peer_id;
|
||||
ether_addr_copy(peer->ml_addr, sta->addr);
|
||||
|
||||
/* the assoc link is considered primary for now */
|
||||
|
|
@ -285,8 +294,13 @@ 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))
|
||||
/*
|
||||
* Only devices that allocate the ID on the host own a slot in
|
||||
* free_ml_peer_id_map.
|
||||
*/
|
||||
if (ah->host_alloc_ml_id &&
|
||||
(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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user