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);
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;
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,
}
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;
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)
/* 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 */
}
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)