[PATCH ath-next 1/2] wifi: ath12k: Prepare ahvif scan link for parallel scan

Mahendran P quic_mahep at quicinc.com
Mon Apr 28 21:36:11 PDT 2025


On 4/28/2025 8:49 PM, Rameshkumar Sundaram wrote:
> When two split-phy devices that support overlapping frequency ranges within
> the same band(say 5 GHz low and 5 GHz high) are grouped into an ath12k
> hardware (HW) setup, they share a common wiphy instance. Consequently, the
> channel list (wiphy->bands[]) becomes unified across all associated
> radios (ar).
> 
> When a scan is triggered with frequency list containing frequencies of
> both 5 GHz low and 5 GHz high, mac80211 generates a single scan request
> to driver with all the frequencies. This is because mac80211 splits the
> scan request based on band.
> 
> ath12k checks the first frequency in the requested scan frequency list and
> initiates scan to corresponding radio's(ar) firmware with all the
> frequencies. Firmware rejects this scan since some of the frequencies in
> the scan request are not supported, resulting in a scan failure.
> To fix this ath12k driver should split the scan request into multiple
> scans based on requested frequencies and schedule them to corresponding
> underlying radio(s) in parallel.
> 
> Currently, ath12k driver assigns the scan link (link 15) in ahvif->links[]
> for scan vdev creation. However, with parallel scan support being
> introduced in the following patch, multiple radios (e.g., 5 GHz low and
> 5 GHz high) in the same HW group may attempt to use the same scan link
> concurrently, causing conflicts where the vdev created by one radio could
> be deleted and re-initialized by another.
> 
> To address this, reserve space for additional scan links for each radio in
> a MLO group and allow subsequent radios to use different available scan
> links (ahvif->link[15..MAX_SCAN_LINKS]) when scan link (15) is
> pre-occupied.
> While at it, rename ATH12K_DEFAULT_SCAN_LINK as ATH12K_FIRST_SCAN_LINK
> as there is no longer only one scan link.
> 
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
> 
> Signed-off-by: Rameshkumar Sundaram <rameshkumar.sundaram at oss.qualcomm.com>
> ---
>  drivers/net/wireless/ath/ath12k/core.h |  2 +-
>  drivers/net/wireless/ath/ath12k/mac.c  | 49 +++++++++++++++++++-------
>  drivers/net/wireless/ath/ath12k/mac.h  |  7 ++--
>  3 files changed, 42 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
> index 4b8f434e3e9a..0d512818ee96 100644
> --- a/drivers/net/wireless/ath/ath12k/core.h
> +++ b/drivers/net/wireless/ath/ath12k/core.h
> @@ -352,7 +352,7 @@ struct ath12k_vif {
>  	struct ath12k_link_vif __rcu *link[ATH12K_NUM_MAX_LINKS];
>  	struct ath12k_vif_cache *cache[IEEE80211_MLD_MAX_NUM_LINKS];
>  	/* indicates bitmap of link vif created in FW */
> -	u16 links_map;
> +	u32 links_map;
>  	u8 last_scan_link;
>  
>  	/* Must be last - ends in a flexible-array member.
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 8949073c0163..6dab2f3a9e0d 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -3483,7 +3483,7 @@ static struct ath12k_link_vif *ath12k_mac_assign_link_vif(struct ath12k_hw *ah,
>  	/* If this is the first link arvif being created for an ML VIF
>  	 * use the preallocated deflink memory except for scan arvifs
>  	 */
> -	if (!ahvif->links_map && link_id != ATH12K_DEFAULT_SCAN_LINK) {
> +	if (!ahvif->links_map && link_id < ATH12K_FIRST_SCAN_LINK) {
>  		arvif = &ahvif->deflink;
>  
>  		if (vif->type == NL80211_IFTYPE_STATION)
> @@ -4475,11 +4475,12 @@ ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
>  	struct ath12k_link_vif *arvif;
>  	struct ath12k_hw *ah = ahvif->ah;
>  	unsigned long links = ahvif->links_map;
> +	unsigned long scan_links_map;
>  	u8 link_id;
>  
>  	lockdep_assert_wiphy(ah->hw->wiphy);
>  
> -	for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
> +	for_each_set_bit(link_id, &links, ATH12K_NUM_MAX_LINKS) {
>  		arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
>  
>  		if (!arvif || !arvif->is_created)
> @@ -4489,10 +4490,20 @@ ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
>  			return link_id;
>  	}
>  
> -	/* input ar is not assigned to any of the links of ML VIF, use scan
> -	 * link (15) for scan vdev creation.
> +	/* input ar is not assigned to any of the links of ML VIF, use next
> +	 * available scan link for scan vdev creation. There are cases where
> +	 * single scan req needs to be split in driver and initiate separate
> +	 * scan requests to firmware based on device.
>  	 */
> -	return ATH12K_DEFAULT_SCAN_LINK;
> +
> +	 /* Unset all non-scan links (0-14) of scan_links_map so that ffs() will
> +	  * choose an available link among scan links (i.e link id >= 15)
> +	  */
> +	scan_links_map = ~ahvif->links_map & ATH12K_SCAN_LINKS_MASK;
> +	if (scan_links_map)
> +		return __ffs(scan_links_map);
> +
> +	return ATH12K_FIRST_SCAN_LINK;
>  }
>  
>  static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
> @@ -4523,9 +4534,16 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
>  
>  	/* check if any of the links of ML VIF is already started on
>  	 * radio(ar) corresponding to given scan frequency and use it,
> -	 * if not use scan link (link 15) for scan purpose.
> +	 * if not use scan link (link id >= 15) for scan purpose.
>  	 */
>  	link_id = ath12k_mac_find_link_id_by_ar(ahvif, ar);
> +	/* All scan links are occupied. ideally this shouldn't happen as
> +	 * mac80211 won't schedule scan for same band until ongoing scan is
> +	 * completed, don't try to exceed max links just in case if it happens.
> +	 */
> +	if (link_id >= ATH12K_NUM_MAX_LINKS)
> +		return -EBUSY;
> +
>  	arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
>  
>  	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac link ID %d selected for scan",
> @@ -8654,7 +8672,8 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
>  	struct ath12k_hw *ah = hw->priv;
>  	struct ath12k *ar;
>  	struct ath12k_base *ab;
> -	u8 link_id = arvif->link_id;
> +	u8 link_id = arvif->link_id, scan_link_id;
> +	unsigned long scan_link_map;
>  	int ret;
>  
>  	lockdep_assert_wiphy(hw->wiphy);
> @@ -8673,12 +8692,16 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
>  	 * and now we want to create for actual usage.
>  	 */
>  	if (ieee80211_vif_is_mld(vif)) {
> -		scan_arvif = wiphy_dereference(hw->wiphy,
> -					       ahvif->link[ATH12K_DEFAULT_SCAN_LINK]);
> -		if (scan_arvif && scan_arvif->ar == ar) {
> -			ar->scan.arvif = NULL;
> -			ath12k_mac_remove_link_interface(hw, scan_arvif);
> -			ath12k_mac_unassign_link_vif(scan_arvif);
> +		scan_link_map = ahvif->links_map & ATH12K_SCAN_LINKS_MASK;
> +		for_each_set_bit(scan_link_id, &scan_link_map, ATH12K_NUM_MAX_LINKS) {
> +			scan_arvif = wiphy_dereference(hw->wiphy,
> +						       ahvif->link[scan_link_id]);
> +			if (scan_arvif && scan_arvif->ar == ar) {
> +				ar->scan.arvif = NULL;
> +				ath12k_mac_remove_link_interface(hw, scan_arvif);
> +				ath12k_mac_unassign_link_vif(scan_arvif);
> +				break;
> +			}
>  		}
>  	}
>  
> diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
> index da37332352fe..8ec4a890172c 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.h
> +++ b/drivers/net/wireless/ath/ath12k/mac.h
> @@ -51,8 +51,11 @@ struct ath12k_generic_iter {
>  /* Default link after the IEEE802.11 defined Max link id limit
>   * for driver usage purpose.
>   */
> -#define ATH12K_DEFAULT_SCAN_LINK	IEEE80211_MLD_MAX_NUM_LINKS
> -#define ATH12K_NUM_MAX_LINKS		(IEEE80211_MLD_MAX_NUM_LINKS + 1)
> +#define ATH12K_FIRST_SCAN_LINK		IEEE80211_MLD_MAX_NUM_LINKS
> +#define ATH12K_SCAN_MAX_LINKS		ATH12K_GROUP_MAX_RADIO
> +/* Define 1 scan link for each radio for parallel scan purposes */
> +#define ATH12K_NUM_MAX_LINKS	(IEEE80211_MLD_MAX_NUM_LINKS + ATH12K_SCAN_MAX_LINKS)
> +#define ATH12K_SCAN_LINKS_MASK	GENMASK(ATH12K_NUM_MAX_LINKS, IEEE80211_MLD_MAX_NUM_LINKS)
>  
>  enum ath12k_supported_bw {
>  	ATH12K_BW_20    = 0,

Reviewed-by: Mahendran P <quic_mahep at quicinc.com>




More information about the ath12k mailing list