[PATCH ath12k-ng] wifi: ath12k: Skip DP peer creation for scan vdev
Baochen Qiang
baochen.qiang at oss.qualcomm.com
Mon Dec 8 17:50:00 PST 2025
On 12/7/2025 3:27 PM, Ripan Deuri wrote:
> Consider a multi-link AP configuration:
>
> MLD vif (MAC addr: aa:bb)
> |-- 2.4 GHz link (BSSID: aa:bb)
> |-- 5 GHz link (BSSID: cc:dd)
>
> For AP vdevs, ath12k creates a DP peer using the arvif's BSSID and stores
> it in dp_hw->dp_peers_list. During scan operations, the driver assigns an
> arvif to the scan vdev and uses the vif's MAC address as its BSSID. In
> the above scenario, the scan vdev MAC address (aa:bb) matches the BSSID
> of the 2.4 GHz AP link, causing a duplicate entry in dp_hw->dp_peers_list
> and leading to scan vdev creation failure.
>
> Failure in vif bringup sequence:
> 1. Create AP vdev for 2.4 GHz link:
> - Assign arvif with BSSID = aa:bb and link_id = 0.
> - Create DP peer with address aa:bb and add to dp_hw->dp_peers_list.
>
> 2. Create scan vdev for 5 GHz link:
> - Assign arvif with BSSID = aa:bb (same as vif MAC address) and
> link_id = 15.
> - Attempt to create another DP peer with address aa:bb.
> - Operation fails because aa:bb already exists in dp_hw->dp_peers_list,
> resulting in duplicate entry conflict.
>
> 3. Delete scan vdev for 5 GHz link.
> 4. Create AP vdev for 5 GHz link.
>
> Since DP peer is not needed for scan operations, identify scan vdev using
> arvif->link_id >= IEEE80211_MLD_MAX_NUM_LINKS and skip DP peer creation
> and deletion.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.5-01651-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Ripan Deuri <quic_rdeuri at quicinc.com>
> ---
> drivers/net/wireless/ath/ath12k/mac.c | 22 ++++++++++++++--------
> drivers/net/wireless/ath/ath12k/peer.c | 12 +++++++-----
> 2 files changed, 21 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 3649f58fef84..42e750376926 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -1229,7 +1229,8 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
>
> /* Delete all the self dp_peers on asserted radio */
> list_for_each_entry_safe_reverse(arvif, tmp_vif, &ar->arvifs, list) {
> - if (arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
> + if ((arvif->ahvif->vdev_type == WMI_VDEV_TYPE_AP) &&
> + (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS)) {
> ath12k_dp_peer_delete(dp_hw, arvif->bssid, NULL);
> arvif->num_stations = 0;
> }
> @@ -4031,7 +4032,8 @@ static void ath12k_mac_remove_link_interface(struct ieee80211_hw *hw,
> ath12k_warn(ar->ab, "failed to submit AP self-peer removal on vdev %d link id %d: %d",
> arvif->vdev_id, arvif->link_id, ret);
>
> - ath12k_dp_peer_delete(&ah->dp_hw, arvif->bssid, NULL);
> + if (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS)
> + ath12k_dp_peer_delete(&ah->dp_hw, arvif->bssid, NULL);
> }
> ath12k_mac_vdev_delete(ar, arvif);
> }
> @@ -9720,6 +9722,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
> u8 link_id;
> struct ath12k_dp_link_vif *dp_link_vif = NULL;
> struct ath12k_dp_peer_create_params params = {};
> + bool dp_peer_created = false;
>
> lockdep_assert_wiphy(hw->wiphy);
>
> @@ -9805,11 +9808,14 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
> case WMI_VDEV_TYPE_AP:
> params.ucast_ra_only = true;
>
> - ret = ath12k_dp_peer_create(&ah->dp_hw, arvif->bssid, ¶ms);
> - if (ret) {
> - ath12k_warn(ab, "failed to vdev %d create dp_peer for AP: %d\n",
> - arvif->vdev_id, ret);
> - goto err_vdev_del;
> + if (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
> + ret = ath12k_dp_peer_create(&ah->dp_hw, arvif->bssid, ¶ms);
> + if (ret) {
> + ath12k_warn(ab, "failed to vdev %d create dp_peer for AP: %d\n",
> + arvif->vdev_id, ret);
> + goto err_vdev_del;
> + }
> + dp_peer_created = true;
> }
>
> peer_param.vdev_id = arvif->vdev_id;
> @@ -9925,7 +9931,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
> }
>
> err_dp_peer_del:
> - if (ahvif->vdev_type == WMI_VDEV_TYPE_AP)
> + if (dp_peer_created)
> ath12k_dp_peer_delete(&ah->dp_hw, arvif->bssid, NULL);
>
> err_vdev_del:
> diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
> index c2fb5bbd6cea..5f3bd3b9a3e9 100644
> --- a/drivers/net/wireless/ath/ath12k/peer.c
> +++ b/drivers/net/wireless/ath/ath12k/peer.c
> @@ -241,11 +241,13 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
>
> spin_unlock_bh(&dp->dp_lock);
>
> - ret = ath12k_dp_link_peer_assign(ath12k_ab_to_dp(ar->ab),
> - &(ath12k_ar_to_ah(ar)->dp_hw),
> - arvif->vdev_id, sta,
> - (u8 *)arg->peer_addr, link_id,
> - ar->hw_link_id);
> + if (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
> + ret = ath12k_dp_link_peer_assign(ath12k_ab_to_dp(ar->ab),
> + &(ath12k_ar_to_ah(ar)->dp_hw),
> + arvif->vdev_id, sta,
> + (u8 *)arg->peer_addr, link_id,
> + ar->hw_link_id);
> + }
>
> return ret;
> }
>
> base-commit: a1e19289932aeef26085feb97597d624da6302ab
Reviewed-by: Baochen Qiang <baochen.qiang at oss.qualcomm.com>
More information about the ath12k
mailing list