summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c49
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.h7
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 7bcd9c70309f..9021e44e17e5 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -380,7 +380,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 1077b19a89c9..d6bd54e48521 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -3499,7 +3499,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)
@@ -4491,11 +4491,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)
@@ -4505,10 +4506,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,
@@ -4539,9 +4550,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",
@@ -9068,7 +9086,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);
@@ -9087,12 +9106,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 cc81b1f5680f..473611bfccdc 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)
#define ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE 2