Commit 5a58414f authored by Ripan Deuri's avatar Ripan Deuri Committed by Jeff Johnson
Browse files

wifi: ath12k: Skip DP peer creation for scan vdev



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: default avatarRipan Deuri <quic_rdeuri@quicinc.com>
Reviewed-by: default avatarBaochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: default avatarVasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20251207072717.95542-1-quic_rdeuri@quicinc.com


Signed-off-by: default avatarJeff Johnson <jeff.johnson@oss.qualcomm.com>
parent a1e19289
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -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,6 +4032,7 @@ 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);

		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,12 +9808,15 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
	case WMI_VDEV_TYPE_AP:
		params.ucast_ra_only = true;

		if (arvif->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
			ret = ath12k_dp_peer_create(&ah->dp_hw, arvif->bssid, &params);
			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;
		peer_param.peer_addr = arvif->bssid;
@@ -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:
+7 −5
Original line number Diff line number Diff line
@@ -241,11 +241,13 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,

	spin_unlock_bh(&dp->dp_lock);

	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;
}