mirror of https://lore.kernel.org/ath12k/
 help / color / mirror / Atom feed
* [PATCH ath-next 0/2] Add split-phy scan support in single wiphy
@ 2025-04-28 15:19 Rameshkumar Sundaram
  2025-04-28 15:19 ` [PATCH ath-next 1/2] wifi: ath12k: Prepare ahvif scan link for parallel scan Rameshkumar Sundaram
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Rameshkumar Sundaram @ 2025-04-28 15:19 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless, Rameshkumar Sundaram

When two split-phy devices having supported frequency range in same band
(as mentioned below) are combined into an ath12k HW group, they will be part
of same wiphy and hence the channel list (wiphy->bands[]) will be common
for all of the radios (ar).

1 - 2.4 GHz + 5 GHz Low band
2 - 5 GHz High band + 6 GHz

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 both the frequencies. This is because mac80211 splits the
the scan request based on band.
This results in driver scheduling scan for both frequencies in same radio,
as driver always assumes that the scan request frequency list from
mac80211 only contains frequencies for one radio.
Split the scan request frequency list based on the supported frequency
ranges of radios in a band and schedule scan to corresponding radios.

Since the scan request is split in ath12k driver internally, wait for
all radios to complete their scan and report the same to mac80211.

Depends-on: https://lore.kernel.org/linux-wireless/20250417-fix_scan_vdev_handling-v3-0-9ec42513d26b@oss.qualcomm.com/
Depends-on: https://lore.kernel.org/linux-wireless/20250417073954.632994-1-rameshkumar.sundaram@oss.qualcomm.com/

Rameshkumar Sundaram (2):
  wifi: ath12k: Prepare ahvif scan link for parallel scan
  wifi: ath12k: Split scan request for split band device

 drivers/net/wireless/ath/ath12k/core.h |   4 +-
 drivers/net/wireless/ath/ath12k/mac.c  | 197 +++++++++++++++++++------
 drivers/net/wireless/ath/ath12k/mac.h  |   7 +-
 3 files changed, 160 insertions(+), 48 deletions(-)


base-commit: 21346cd925c2567d5f56cdb1421c94815ac10221
prerequisite-patch-id: 621a0dbeb6269fcaf27c808f951d9e2a2c3ac8f7
prerequisite-patch-id: a9eebd8a3cc3b1ed9ed3574ce9fee088af9c5798
-- 
2.34.1



^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH ath-next 1/2] wifi: ath12k: Prepare ahvif scan link for parallel scan
  2025-04-28 15:19 [PATCH ath-next 0/2] Add split-phy scan support in single wiphy Rameshkumar Sundaram
@ 2025-04-28 15:19 ` Rameshkumar Sundaram
  2025-04-29  4:36   ` Mahendran P
  2025-04-28 15:19 ` [PATCH ath-next 2/2] wifi: ath12k: Split scan request for split band device Rameshkumar Sundaram
  2025-05-02 20:55 ` [PATCH ath-next 0/2] Add split-phy scan support in single wiphy Jeff Johnson
  2 siblings, 1 reply; 7+ messages in thread
From: Rameshkumar Sundaram @ 2025-04-28 15:19 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless, Rameshkumar Sundaram

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@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,
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH ath-next 2/2] wifi: ath12k: Split scan request for split band device
  2025-04-28 15:19 [PATCH ath-next 0/2] Add split-phy scan support in single wiphy Rameshkumar Sundaram
  2025-04-28 15:19 ` [PATCH ath-next 1/2] wifi: ath12k: Prepare ahvif scan link for parallel scan Rameshkumar Sundaram
@ 2025-04-28 15:19 ` Rameshkumar Sundaram
  2025-04-29  4:36   ` Mahendran P
  2025-05-02 20:55 ` [PATCH ath-next 0/2] Add split-phy scan support in single wiphy Jeff Johnson
  2 siblings, 1 reply; 7+ messages in thread
From: Rameshkumar Sundaram @ 2025-04-28 15:19 UTC (permalink / raw)
  To: ath12k; +Cc: linux-wireless, Rameshkumar Sundaram, Vignesh C

When two split-phy devices having supported frequency range in same band
(as mentioned below) are combined into an ath12k HW group, they will be
part of same wiphy and hence the channel list (wiphy->bands[]) will be
common for all of the radios (ar).

1 - 2.4 GHz + 5 GHz Low band
2 - 5 GHz High band + 6 GHz

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 both 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 as some frequencies in the scan
request are not supported, resulting is scan failure.

Fix this by splitting the scan request into multiples scans in driver
based on the supported frequency range of different radios in a band and
schedule scans in parallel to them.
Finally send scan completion/abort notification to mac80211 after all the
radios complete their scheduled scan.

Also, last_scan_link is not needed anymore as ath12k internally schedules
multiple scans, remove the same and use ahvif->links_map to identify
scan links when scan is cancelled.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1

Co-developed-by: Vignesh C <quic_vignc@quicinc.com>
Signed-off-by: Vignesh C <quic_vignc@quicinc.com>
Signed-off-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
---
 drivers/net/wireless/ath/ath12k/core.h |   2 -
 drivers/net/wireless/ath/ath12k/mac.c  | 148 ++++++++++++++++++++-----
 2 files changed, 118 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 0d512818ee96..c8fd0b29aaa1 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -353,8 +353,6 @@ struct ath12k_vif {
 	struct ath12k_vif_cache *cache[IEEE80211_MLD_MAX_NUM_LINKS];
 	/* indicates bitmap of link vif created in FW */
 	u32 links_map;
-	u8 last_scan_link;
-
 	/* Must be last - ends in a flexible-array member.
 	 *
 	 * FIXME: Driver should not copy struct ieee80211_chanctx_conf,
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 6dab2f3a9e0d..236e3ee22d4d 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -4249,6 +4249,23 @@ static void ath12k_scan_timeout_work(struct work_struct *work)
 	wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
 }
 
+static void ath12k_mac_scan_send_complete(struct ath12k *ar,
+					  struct cfg80211_scan_info *info)
+{
+	struct ath12k_hw *ah = ar->ah;
+	struct ath12k *partner_ar;
+	int i;
+
+	lockdep_assert_wiphy(ah->hw->wiphy);
+
+	for_each_ar(ah, partner_ar, i)
+		if (partner_ar != ar &&
+		    partner_ar->scan.state == ATH12K_SCAN_RUNNING)
+			return;
+
+	ieee80211_scan_completed(ah->hw, info);
+}
+
 static void ath12k_scan_vdev_clean_work(struct wiphy *wiphy, struct wiphy_work *work)
 {
 	struct ath12k *ar = container_of(work, struct ath12k,
@@ -4287,7 +4304,7 @@ static void ath12k_scan_vdev_clean_work(struct wiphy *wiphy, struct wiphy_work *
 				    ATH12K_SCAN_STARTING)),
 		};
 
-		ieee80211_scan_completed(ar->ah->hw, &info);
+		ath12k_mac_scan_send_complete(ar, &info);
 	}
 
 	ar->scan.state = ATH12K_SCAN_IDLE;
@@ -4506,12 +4523,14 @@ ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
 	return ATH12K_FIRST_SCAN_LINK;
 }
 
-static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
-				 struct ieee80211_vif *vif,
-				 struct ieee80211_scan_request *hw_req)
+static int ath12k_mac_initiate_hw_scan(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_scan_request *hw_req,
+				       int n_channels,
+				       struct ieee80211_channel **chan_list,
+				       struct ath12k *ar)
 {
 	struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
-	struct ath12k *ar;
 	struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
 	struct ath12k_link_vif *arvif;
 	struct cfg80211_scan_request *req = &hw_req->req;
@@ -4525,13 +4544,6 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
 
 	arvif = &ahvif->deflink;
 
-	/* Since the targeted scan device could depend on the frequency
-	 * requested in the hw_req, select the corresponding radio
-	 */
-	ar = ath12k_mac_select_scan_device(hw, vif, hw_req->req.channels[0]->center_freq);
-	if (!ar)
-		return -EINVAL;
-
 	/* 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 id >= 15) for scan purpose.
@@ -4634,8 +4646,8 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
 		arg->scan_f_passive = 1;
 	}
 
-	if (req->n_channels) {
-		arg->num_chan = req->n_channels;
+	if (n_channels) {
+		arg->num_chan = n_channels;
 		arg->chan_list = kcalloc(arg->num_chan, sizeof(*arg->chan_list),
 					 GFP_KERNEL);
 		if (!arg->chan_list) {
@@ -4644,7 +4656,7 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
 		}
 
 		for (i = 0; i < arg->num_chan; i++)
-			arg->chan_list[i] = req->channels[i]->center_freq;
+			arg->chan_list[i] = chan_list[i]->center_freq;
 	}
 
 	ret = ath12k_start_scan(ar, arg);
@@ -4662,13 +4674,6 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
 
 	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac scan started");
 
-	/* As per cfg80211/mac80211 scan design, it allows only one
-	 * scan at a time. Hence last_scan link id is used for
-	 * tracking the link id on which the scan is been done on
-	 * this vif.
-	 */
-	ahvif->last_scan_link = arvif->link_id;
-
 	/* Add a margin to account for event/command processing */
 	ieee80211_queue_delayed_work(ath12k_ar_to_hw(ar), &ar->scan.timeout,
 				     msecs_to_jiffies(arg->max_scan_time +
@@ -4689,25 +4694,108 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
 	return ret;
 }
 
+static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
+				 struct ieee80211_vif *vif,
+				 struct ieee80211_scan_request *hw_req)
+{
+	struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+	struct ieee80211_channel **chan_list, *chan;
+	struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+	unsigned long links_map, link_id;
+	struct ath12k_link_vif *arvif;
+	struct ath12k *ar, *scan_ar;
+	int i, j, ret = 0;
+
+	lockdep_assert_wiphy(hw->wiphy);
+
+	chan_list = kcalloc(hw_req->req.n_channels, sizeof(*chan_list), GFP_KERNEL);
+	if (!chan_list)
+		return -ENOMEM;
+
+	/* There could be channels that belong to multiple underlying radio
+	 * in same scan request as mac80211 sees it as single band. In that
+	 * case split the hw_req based on frequency range and schedule scans to
+	 * corresponding radio.
+	 */
+	for_each_ar(ah, ar, i) {
+		int n_chans = 0;
+
+		for (j = 0; j < hw_req->req.n_channels; j++) {
+			chan = hw_req->req.channels[j];
+			scan_ar = ath12k_mac_select_scan_device(hw, vif,
+								chan->center_freq);
+			if (!scan_ar) {
+				ath12k_hw_warn(ah, "unable to select scan device for freq %d\n",
+					       chan->center_freq);
+				ret = -EINVAL;
+				goto abort;
+			}
+			if (ar != scan_ar)
+				continue;
+
+			chan_list[n_chans++] = chan;
+		}
+		if (n_chans) {
+			ret = ath12k_mac_initiate_hw_scan(hw, vif, hw_req, n_chans,
+							  chan_list, ar);
+			if (ret)
+				goto abort;
+		}
+	}
+abort:
+	/* If any of the parallel scans initiated fails, abort all and
+	 * remove the scan interfaces created. Return complete scan
+	 * failure as mac80211 assumes this as single scan request.
+	 */
+	if (ret) {
+		ath12k_hw_warn(ah, "Scan failed %d , cleanup all scan vdevs\n", ret);
+		links_map = ahvif->links_map;
+		for_each_set_bit(link_id, &links_map, ATH12K_NUM_MAX_LINKS) {
+			arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+			if (!arvif)
+				continue;
+
+			ar = arvif->ar;
+			if (ar->scan.arvif == arvif) {
+				wiphy_work_cancel(hw->wiphy, &ar->scan.vdev_clean_wk);
+				spin_lock_bh(&ar->data_lock);
+				ar->scan.arvif = NULL;
+				ar->scan.state = ATH12K_SCAN_IDLE;
+				ar->scan_channel = NULL;
+				ar->scan.roc_freq = 0;
+				spin_unlock_bh(&ar->data_lock);
+			}
+			if (link_id >= ATH12K_FIRST_SCAN_LINK) {
+				ath12k_mac_remove_link_interface(hw, arvif);
+				ath12k_mac_unassign_link_vif(arvif);
+			}
+		}
+	}
+	kfree(chan_list);
+	return ret;
+}
+
 static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
 					 struct ieee80211_vif *vif)
 {
 	struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
-	u16 link_id = ahvif->last_scan_link;
+	unsigned long link_id, links_map = ahvif->links_map;
 	struct ath12k_link_vif *arvif;
 	struct ath12k *ar;
 
 	lockdep_assert_wiphy(hw->wiphy);
 
-	arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
-	if (!arvif || arvif->is_started)
-		return;
+	for_each_set_bit(link_id, &links_map, ATH12K_NUM_MAX_LINKS) {
+		arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+		if (!arvif || arvif->is_started)
+			continue;
 
-	ar = arvif->ar;
+		ar = arvif->ar;
 
-	ath12k_scan_abort(ar);
+		ath12k_scan_abort(ar);
 
-	cancel_delayed_work_sync(&ar->scan.timeout);
+		cancel_delayed_work_sync(&ar->scan.timeout);
+	}
 }
 
 static int ath12k_install_key(struct ath12k_link_vif *arvif,
@@ -8917,7 +9005,7 @@ static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
 					.aborted = true,
 				};
 
-				ieee80211_scan_completed(ar->ah->hw, &info);
+				ath12k_mac_scan_send_complete(ar, &info);
 			}
 
 			ar->scan.state = ATH12K_SCAN_IDLE;
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH ath-next 1/2] wifi: ath12k: Prepare ahvif scan link for parallel scan
  2025-04-28 15:19 ` [PATCH ath-next 1/2] wifi: ath12k: Prepare ahvif scan link for parallel scan Rameshkumar Sundaram
@ 2025-04-29  4:36   ` Mahendran P
  0 siblings, 0 replies; 7+ messages in thread
From: Mahendran P @ 2025-04-29  4:36 UTC (permalink / raw)
  To: Rameshkumar Sundaram, ath12k; +Cc: linux-wireless

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@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@quicinc.com>



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH ath-next 2/2] wifi: ath12k: Split scan request for split band device
  2025-04-28 15:19 ` [PATCH ath-next 2/2] wifi: ath12k: Split scan request for split band device Rameshkumar Sundaram
@ 2025-04-29  4:36   ` Mahendran P
  0 siblings, 0 replies; 7+ messages in thread
From: Mahendran P @ 2025-04-29  4:36 UTC (permalink / raw)
  To: Rameshkumar Sundaram, ath12k; +Cc: linux-wireless, Vignesh C

On 4/28/2025 8:49 PM, Rameshkumar Sundaram wrote:
> When two split-phy devices having supported frequency range in same band
> (as mentioned below) are combined into an ath12k HW group, they will be
> part of same wiphy and hence the channel list (wiphy->bands[]) will be
> common for all of the radios (ar).
> 
> 1 - 2.4 GHz + 5 GHz Low band
> 2 - 5 GHz High band + 6 GHz
> 
> 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 both 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 as some frequencies in the scan
> request are not supported, resulting is scan failure.
> 
> Fix this by splitting the scan request into multiples scans in driver
> based on the supported frequency range of different radios in a band and
> schedule scans in parallel to them.
> Finally send scan completion/abort notification to mac80211 after all the
> radios complete their scheduled scan.
> 
> Also, last_scan_link is not needed anymore as ath12k internally schedules
> multiple scans, remove the same and use ahvif->links_map to identify
> scan links when scan is cancelled.
> 
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1
> 
> Co-developed-by: Vignesh C <quic_vignc@quicinc.com>
> Signed-off-by: Vignesh C <quic_vignc@quicinc.com>
> Signed-off-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
> ---
>  drivers/net/wireless/ath/ath12k/core.h |   2 -
>  drivers/net/wireless/ath/ath12k/mac.c  | 148 ++++++++++++++++++++-----
>  2 files changed, 118 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
> index 0d512818ee96..c8fd0b29aaa1 100644
> --- a/drivers/net/wireless/ath/ath12k/core.h
> +++ b/drivers/net/wireless/ath/ath12k/core.h
> @@ -353,8 +353,6 @@ struct ath12k_vif {
>  	struct ath12k_vif_cache *cache[IEEE80211_MLD_MAX_NUM_LINKS];
>  	/* indicates bitmap of link vif created in FW */
>  	u32 links_map;
> -	u8 last_scan_link;
> -
>  	/* Must be last - ends in a flexible-array member.
>  	 *
>  	 * FIXME: Driver should not copy struct ieee80211_chanctx_conf,
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 6dab2f3a9e0d..236e3ee22d4d 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -4249,6 +4249,23 @@ static void ath12k_scan_timeout_work(struct work_struct *work)
>  	wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
>  }
>  
> +static void ath12k_mac_scan_send_complete(struct ath12k *ar,
> +					  struct cfg80211_scan_info *info)
> +{
> +	struct ath12k_hw *ah = ar->ah;
> +	struct ath12k *partner_ar;
> +	int i;
> +
> +	lockdep_assert_wiphy(ah->hw->wiphy);
> +
> +	for_each_ar(ah, partner_ar, i)
> +		if (partner_ar != ar &&
> +		    partner_ar->scan.state == ATH12K_SCAN_RUNNING)
> +			return;
> +
> +	ieee80211_scan_completed(ah->hw, info);
> +}
> +
>  static void ath12k_scan_vdev_clean_work(struct wiphy *wiphy, struct wiphy_work *work)
>  {
>  	struct ath12k *ar = container_of(work, struct ath12k,
> @@ -4287,7 +4304,7 @@ static void ath12k_scan_vdev_clean_work(struct wiphy *wiphy, struct wiphy_work *
>  				    ATH12K_SCAN_STARTING)),
>  		};
>  
> -		ieee80211_scan_completed(ar->ah->hw, &info);
> +		ath12k_mac_scan_send_complete(ar, &info);
>  	}
>  
>  	ar->scan.state = ATH12K_SCAN_IDLE;
> @@ -4506,12 +4523,14 @@ ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
>  	return ATH12K_FIRST_SCAN_LINK;
>  }
>  
> -static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
> -				 struct ieee80211_vif *vif,
> -				 struct ieee80211_scan_request *hw_req)
> +static int ath12k_mac_initiate_hw_scan(struct ieee80211_hw *hw,
> +				       struct ieee80211_vif *vif,
> +				       struct ieee80211_scan_request *hw_req,
> +				       int n_channels,
> +				       struct ieee80211_channel **chan_list,
> +				       struct ath12k *ar)
>  {
>  	struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
> -	struct ath12k *ar;
>  	struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
>  	struct ath12k_link_vif *arvif;
>  	struct cfg80211_scan_request *req = &hw_req->req;
> @@ -4525,13 +4544,6 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
>  
>  	arvif = &ahvif->deflink;
>  
> -	/* Since the targeted scan device could depend on the frequency
> -	 * requested in the hw_req, select the corresponding radio
> -	 */
> -	ar = ath12k_mac_select_scan_device(hw, vif, hw_req->req.channels[0]->center_freq);
> -	if (!ar)
> -		return -EINVAL;
> -
>  	/* 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 id >= 15) for scan purpose.
> @@ -4634,8 +4646,8 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
>  		arg->scan_f_passive = 1;
>  	}
>  
> -	if (req->n_channels) {
> -		arg->num_chan = req->n_channels;
> +	if (n_channels) {
> +		arg->num_chan = n_channels;
>  		arg->chan_list = kcalloc(arg->num_chan, sizeof(*arg->chan_list),
>  					 GFP_KERNEL);
>  		if (!arg->chan_list) {
> @@ -4644,7 +4656,7 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
>  		}
>  
>  		for (i = 0; i < arg->num_chan; i++)
> -			arg->chan_list[i] = req->channels[i]->center_freq;
> +			arg->chan_list[i] = chan_list[i]->center_freq;
>  	}
>  
>  	ret = ath12k_start_scan(ar, arg);
> @@ -4662,13 +4674,6 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
>  
>  	ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac scan started");
>  
> -	/* As per cfg80211/mac80211 scan design, it allows only one
> -	 * scan at a time. Hence last_scan link id is used for
> -	 * tracking the link id on which the scan is been done on
> -	 * this vif.
> -	 */
> -	ahvif->last_scan_link = arvif->link_id;
> -
>  	/* Add a margin to account for event/command processing */
>  	ieee80211_queue_delayed_work(ath12k_ar_to_hw(ar), &ar->scan.timeout,
>  				     msecs_to_jiffies(arg->max_scan_time +
> @@ -4689,25 +4694,108 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
>  	return ret;
>  }
>  
> +static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
> +				 struct ieee80211_vif *vif,
> +				 struct ieee80211_scan_request *hw_req)
> +{
> +	struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
> +	struct ieee80211_channel **chan_list, *chan;
> +	struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
> +	unsigned long links_map, link_id;
> +	struct ath12k_link_vif *arvif;
> +	struct ath12k *ar, *scan_ar;
> +	int i, j, ret = 0;
> +
> +	lockdep_assert_wiphy(hw->wiphy);
> +
> +	chan_list = kcalloc(hw_req->req.n_channels, sizeof(*chan_list), GFP_KERNEL);
> +	if (!chan_list)
> +		return -ENOMEM;
> +
> +	/* There could be channels that belong to multiple underlying radio
> +	 * in same scan request as mac80211 sees it as single band. In that
> +	 * case split the hw_req based on frequency range and schedule scans to
> +	 * corresponding radio.
> +	 */
> +	for_each_ar(ah, ar, i) {
> +		int n_chans = 0;
> +
> +		for (j = 0; j < hw_req->req.n_channels; j++) {
> +			chan = hw_req->req.channels[j];
> +			scan_ar = ath12k_mac_select_scan_device(hw, vif,
> +								chan->center_freq);
> +			if (!scan_ar) {
> +				ath12k_hw_warn(ah, "unable to select scan device for freq %d\n",
> +					       chan->center_freq);
> +				ret = -EINVAL;
> +				goto abort;
> +			}
> +			if (ar != scan_ar)
> +				continue;
> +
> +			chan_list[n_chans++] = chan;
> +		}
> +		if (n_chans) {
> +			ret = ath12k_mac_initiate_hw_scan(hw, vif, hw_req, n_chans,
> +							  chan_list, ar);
> +			if (ret)
> +				goto abort;
> +		}
> +	}
> +abort:
> +	/* If any of the parallel scans initiated fails, abort all and
> +	 * remove the scan interfaces created. Return complete scan
> +	 * failure as mac80211 assumes this as single scan request.
> +	 */
> +	if (ret) {
> +		ath12k_hw_warn(ah, "Scan failed %d , cleanup all scan vdevs\n", ret);
> +		links_map = ahvif->links_map;
> +		for_each_set_bit(link_id, &links_map, ATH12K_NUM_MAX_LINKS) {
> +			arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
> +			if (!arvif)
> +				continue;
> +
> +			ar = arvif->ar;
> +			if (ar->scan.arvif == arvif) {
> +				wiphy_work_cancel(hw->wiphy, &ar->scan.vdev_clean_wk);
> +				spin_lock_bh(&ar->data_lock);
> +				ar->scan.arvif = NULL;
> +				ar->scan.state = ATH12K_SCAN_IDLE;
> +				ar->scan_channel = NULL;
> +				ar->scan.roc_freq = 0;
> +				spin_unlock_bh(&ar->data_lock);
> +			}
> +			if (link_id >= ATH12K_FIRST_SCAN_LINK) {
> +				ath12k_mac_remove_link_interface(hw, arvif);
> +				ath12k_mac_unassign_link_vif(arvif);
> +			}
> +		}
> +	}
> +	kfree(chan_list);
> +	return ret;
> +}
> +
>  static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
>  					 struct ieee80211_vif *vif)
>  {
>  	struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
> -	u16 link_id = ahvif->last_scan_link;
> +	unsigned long link_id, links_map = ahvif->links_map;
>  	struct ath12k_link_vif *arvif;
>  	struct ath12k *ar;
>  
>  	lockdep_assert_wiphy(hw->wiphy);
>  
> -	arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
> -	if (!arvif || arvif->is_started)
> -		return;
> +	for_each_set_bit(link_id, &links_map, ATH12K_NUM_MAX_LINKS) {
> +		arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
> +		if (!arvif || arvif->is_started)
> +			continue;
>  
> -	ar = arvif->ar;
> +		ar = arvif->ar;
>  
> -	ath12k_scan_abort(ar);
> +		ath12k_scan_abort(ar);
>  
> -	cancel_delayed_work_sync(&ar->scan.timeout);
> +		cancel_delayed_work_sync(&ar->scan.timeout);
> +	}
>  }
>  
>  static int ath12k_install_key(struct ath12k_link_vif *arvif,
> @@ -8917,7 +9005,7 @@ static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
>  					.aborted = true,
>  				};
>  
> -				ieee80211_scan_completed(ar->ah->hw, &info);
> +				ath12k_mac_scan_send_complete(ar, &info);
>  			}
>  
>  			ar->scan.state = ATH12K_SCAN_IDLE;

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



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH ath-next 0/2] Add split-phy scan support in single wiphy
  2025-04-28 15:19 [PATCH ath-next 0/2] Add split-phy scan support in single wiphy Rameshkumar Sundaram
  2025-04-28 15:19 ` [PATCH ath-next 1/2] wifi: ath12k: Prepare ahvif scan link for parallel scan Rameshkumar Sundaram
  2025-04-28 15:19 ` [PATCH ath-next 2/2] wifi: ath12k: Split scan request for split band device Rameshkumar Sundaram
@ 2025-05-02 20:55 ` Jeff Johnson
  2025-05-06 10:58   ` Rameshkumar Sundaram
  2 siblings, 1 reply; 7+ messages in thread
From: Jeff Johnson @ 2025-05-02 20:55 UTC (permalink / raw)
  To: Rameshkumar Sundaram, ath12k; +Cc: linux-wireless

On 4/28/2025 8:19 AM, Rameshkumar Sundaram wrote:
> When two split-phy devices having supported frequency range in same band
> (as mentioned below) are combined into an ath12k HW group, they will be part
> of same wiphy and hence the channel list (wiphy->bands[]) will be common
> for all of the radios (ar).
> 
> 1 - 2.4 GHz + 5 GHz Low band
> 2 - 5 GHz High band + 6 GHz
> 
> 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 both the frequencies. This is because mac80211 splits the
> the scan request based on band.
> This results in driver scheduling scan for both frequencies in same radio,
> as driver always assumes that the scan request frequency list from
> mac80211 only contains frequencies for one radio.
> Split the scan request frequency list based on the supported frequency
> ranges of radios in a band and schedule scan to corresponding radios.
> 
> Since the scan request is split in ath12k driver internally, wait for
> all radios to complete their scan and report the same to mac80211.
> 
> Depends-on: https://lore.kernel.org/linux-wireless/20250417-fix_scan_vdev_handling-v3-0-9ec42513d26b@oss.qualcomm.com/
> Depends-on: https://lore.kernel.org/linux-wireless/20250417073954.632994-1-rameshkumar.sundaram@oss.qualcomm.com/
> 
> Rameshkumar Sundaram (2):
>   wifi: ath12k: Prepare ahvif scan link for parallel scan
>   wifi: ath12k: Split scan request for split band device
> 
>  drivers/net/wireless/ath/ath12k/core.h |   4 +-
>  drivers/net/wireless/ath/ath12k/mac.c  | 197 +++++++++++++++++++------
>  drivers/net/wireless/ath/ath12k/mac.h  |   7 +-
>  3 files changed, 160 insertions(+), 48 deletions(-)
> 
> 
> base-commit: 21346cd925c2567d5f56cdb1421c94815ac10221
> prerequisite-patch-id: 621a0dbeb6269fcaf27c808f951d9e2a2c3ac8f7
> prerequisite-patch-id: a9eebd8a3cc3b1ed9ed3574ce9fee088af9c5798

While this series applies cleanly on top of ath-next + the dependencies, it
does not apply cleanly on the pending branch (which already contains the
dependencies).

Can you please rebase on ath/main-pending, and post a v2 with ath-pending as
the destination branch tag? Don't worry if the patchwork bot ignores it due to
an unknown branch tag.

/jeff


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH ath-next 0/2] Add split-phy scan support in single wiphy
  2025-05-02 20:55 ` [PATCH ath-next 0/2] Add split-phy scan support in single wiphy Jeff Johnson
@ 2025-05-06 10:58   ` Rameshkumar Sundaram
  0 siblings, 0 replies; 7+ messages in thread
From: Rameshkumar Sundaram @ 2025-05-06 10:58 UTC (permalink / raw)
  To: Jeff Johnson, ath12k; +Cc: linux-wireless



On 5/3/2025 2:25 AM, Jeff Johnson wrote:
> On 4/28/2025 8:19 AM, Rameshkumar Sundaram wrote:
>> When two split-phy devices having supported frequency range in same band
>> (as mentioned below) are combined into an ath12k HW group, they will be part
>> of same wiphy and hence the channel list (wiphy->bands[]) will be common
>> for all of the radios (ar).
>>
>> 1 - 2.4 GHz + 5 GHz Low band
>> 2 - 5 GHz High band + 6 GHz
>>
>> 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 both the frequencies. This is because mac80211 splits the
>> the scan request based on band.
>> This results in driver scheduling scan for both frequencies in same radio,
>> as driver always assumes that the scan request frequency list from
>> mac80211 only contains frequencies for one radio.
>> Split the scan request frequency list based on the supported frequency
>> ranges of radios in a band and schedule scan to corresponding radios.
>>
>> Since the scan request is split in ath12k driver internally, wait for
>> all radios to complete their scan and report the same to mac80211.
>>
>> Depends-on: https://lore.kernel.org/linux-wireless/20250417-fix_scan_vdev_handling-v3-0-9ec42513d26b@oss.qualcomm.com/
>> Depends-on: https://lore.kernel.org/linux-wireless/20250417073954.632994-1-rameshkumar.sundaram@oss.qualcomm.com/
>>
>> Rameshkumar Sundaram (2):
>>    wifi: ath12k: Prepare ahvif scan link for parallel scan
>>    wifi: ath12k: Split scan request for split band device
>>
>>   drivers/net/wireless/ath/ath12k/core.h |   4 +-
>>   drivers/net/wireless/ath/ath12k/mac.c  | 197 +++++++++++++++++++------
>>   drivers/net/wireless/ath/ath12k/mac.h  |   7 +-
>>   3 files changed, 160 insertions(+), 48 deletions(-)
>>
>>
>> base-commit: 21346cd925c2567d5f56cdb1421c94815ac10221
>> prerequisite-patch-id: 621a0dbeb6269fcaf27c808f951d9e2a2c3ac8f7
>> prerequisite-patch-id: a9eebd8a3cc3b1ed9ed3574ce9fee088af9c5798
> 
> While this series applies cleanly on top of ath-next + the dependencies, it
> does not apply cleanly on the pending branch (which already contains the
> dependencies).
> 
> Can you please rebase on ath/main-pending, and post a v2 with ath-pending as
> the destination branch tag? Don't worry if the patchwork bot ignores it due to
> an unknown branch tag.
> 
> /jeff


Sure, will rebase on ath/main-pending and post it.

-- 
--
Ramesh



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-05-06 13:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-28 15:19 [PATCH ath-next 0/2] Add split-phy scan support in single wiphy Rameshkumar Sundaram
2025-04-28 15:19 ` [PATCH ath-next 1/2] wifi: ath12k: Prepare ahvif scan link for parallel scan Rameshkumar Sundaram
2025-04-29  4:36   ` Mahendran P
2025-04-28 15:19 ` [PATCH ath-next 2/2] wifi: ath12k: Split scan request for split band device Rameshkumar Sundaram
2025-04-29  4:36   ` Mahendran P
2025-05-02 20:55 ` [PATCH ath-next 0/2] Add split-phy scan support in single wiphy Jeff Johnson
2025-05-06 10:58   ` Rameshkumar Sundaram

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox