Explorar o código

qcacmn: Allow FW to scan 6G chan based on RNR flag only

First host checks below two things in host scan request:
1. Userspace sets NL80211_SCAN_FLAG_COLOCATED_6GHZ flag
in host scan request.
2. At least one 6G channel is present in the host scan req.

If any of the above conditions satisfies, Host fills all
remaining (other than channel(s) present in host scan req)
valid 6 GHz channel(s) to scan requests and set the flag
FLAG_SCAN_ONLY_IF_RNR_FOUND for each remaining channel(s).

Host sends this updated channel list via WMI command
WMI_START_SCAN_CMDID_param_tlvs->channel_list for host scan
to firmware.

With this change, driver allows Firmware to scan 6G channels
based on RNR IEs only (for colocated APs reported by 2.4/5
GHz APs).

Change-Id: I2d9d2aac58bbc521b2476756d5919647bdc265cc
CRs-Fixed: 3103873
abhinav kumar %!s(int64=3) %!d(string=hai) anos
pai
achega
9c2ce46fc6

+ 25 - 1
os_if/linux/scan/src/wlan_cfg80211_scan.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -1304,6 +1304,27 @@ void wlan_cfg80211_cleanup_scan_queue(struct wlan_objmgr_pdev *pdev,
 	return;
 }
 
+/**
+ * wlan_cfg80211_is_colocated_6ghz_scan_supported() - Check whether colocated
+ * 6ghz scan flag present in scan request or not
+ * @scan_flag: Flags bitmap coming from kernel
+ *
+ * Return: True if colocated 6ghz scan flag present in scan req
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
+static bool
+wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag)
+{
+	return !!(scan_flag & NL80211_SCAN_FLAG_COLOCATED_6GHZ);
+}
+#else
+static inline bool
+wlan_cfg80211_is_colocated_6ghz_scan_supported(uint32_t scan_flag)
+{
+	return false;
+}
+#endif
+
 /**
  * wlan_cfg80211_update_scan_policy_type_flags() - Set scan flags according to
  * scan request
@@ -1323,6 +1344,9 @@ static void wlan_cfg80211_update_scan_policy_type_flags(
 		scan_req->scan_policy_low_span = true;
 	if (req->flags & NL80211_SCAN_FLAG_LOW_POWER)
 		scan_req->scan_policy_low_power = true;
+
+	if (wlan_cfg80211_is_colocated_6ghz_scan_supported(req->flags))
+		scan_req->scan_policy_colocated_6ghz = true;
 }
 #else
 static inline void wlan_cfg80211_update_scan_policy_type_flags(

+ 97 - 0
umac/scan/core/src/wlan_scan_manager_6ghz.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -244,6 +245,92 @@ scm_is_scan_type_exempted_from_optimization(struct scan_start_request *req)
 	return (req->scan_req.scan_type == SCAN_TYPE_RRM);
 }
 
+/**
+ * scm_add_all_valid_6g_channels() - Add all valid 6g channels to scan request
+ * @vdev: vdev on which scan request is issued
+ * @req: Scan start request
+ * @num_scan_ch: Total number of scan channels
+ *
+ * If colocated 6ghz scan flag present in host scan request or at least one 6G
+ * channel is present in the host scan request, then this API
+ * fills all remaining (other than channel(s) resent in host scan req) valid
+ * 6 GHz channel(s) to scan requests channel list and set the flag
+ * FLAG_SCAN_ONLY_IF_RNR_FOUND for each of those added channels.
+ * By this driver allows Firmware to scan 6G channels based on RNR IEs only.
+ *
+ * Return: None
+ */
+static void scm_add_all_valid_6g_channels(struct wlan_objmgr_pdev *pdev,
+					  struct scan_start_request *req,
+					  uint8_t *num_scan_ch)
+{
+	uint8_t i, j;
+	enum channel_enum freq_idx;
+	struct chan_list *chan_list = &req->scan_req.chan_list;
+	struct regulatory_channel *cur_chan_list;
+	bool is_6g_ch_present = false, found;
+	QDF_STATUS status;
+	uint8_t temp_num_chan = 0;
+
+	for (i = 0; i < chan_list->num_chan; i++) {
+		if (wlan_reg_is_6ghz_chan_freq(chan_list->chan[i].freq)) {
+			scm_debug("At least one 6G chan present in scan req:%d",
+				  chan_list->chan[i].freq);
+			is_6g_ch_present = true;
+			break;
+		}
+	}
+
+	if (!is_6g_ch_present &&
+	    !req->scan_req.scan_policy_colocated_6ghz) {
+		scm_debug("Neither 6G chan present nor flag set in scan req");
+		return;
+	}
+
+	cur_chan_list = qdf_mem_malloc(NUM_CHANNELS *
+				sizeof(struct regulatory_channel));
+	if (!cur_chan_list)
+		return;
+
+	status = wlan_reg_get_current_chan_list(pdev, cur_chan_list);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		qdf_mem_free(cur_chan_list);
+		scm_debug("Failed to get cur_chan list");
+		return;
+	}
+
+	freq_idx =
+		wlan_reg_get_chan_enum_for_freq(wlan_reg_min_6ghz_chan_freq());
+	if (freq_idx == INVALID_CHANNEL)
+		return;
+
+	scm_debug("freq_idx:%d", freq_idx);
+	temp_num_chan = chan_list->num_chan;
+	for (i = freq_idx; i < NUM_CHANNELS; i++) {
+		found = false;
+		for (j = 0; j < temp_num_chan; j++) {
+			if (cur_chan_list[i].center_freq ==
+			    chan_list->chan[j].freq) {
+				found = true;
+				break;
+			}
+		}
+		if (!found && cur_chan_list[i].state != CHANNEL_STATE_DISABLE &&
+		    cur_chan_list[i].state != CHANNEL_STATE_INVALID) {
+			chan_list->chan[chan_list->num_chan].freq =
+						cur_chan_list[i].center_freq;
+			chan_list->chan[chan_list->num_chan].flags =
+						FLAG_SCAN_ONLY_IF_RNR_FOUND;
+			chan_list->num_chan++;
+		}
+	}
+
+	scm_debug("prev num_chan:%d, current num_chan:%d", temp_num_chan,
+		  chan_list->num_chan);
+	*num_scan_ch = chan_list->num_chan;
+	qdf_mem_free(cur_chan_list);
+}
+
 static void
 scm_copy_valid_channels(struct wlan_objmgr_psoc *psoc,
 			enum scan_mode_6ghz scan_mode,
@@ -418,6 +505,16 @@ scm_update_6ghz_channel_list(struct scan_start_request *req,
 			scm_set_rnr_flag_non_psc_6g_ch(&chan_list->chan[0],
 						       num_scan_ch);
 		break;
+	case SCAN_MODE_6G_ALL_CHANNEL:
+		/*
+		 * When the ini is set to SCAN_MODE_6G_ALL_CHANNEL,
+		 * Host fills all remaining (other than channel(s) present in
+		 * host scan req) valid 6 GHz channel(s) to scan requests and
+		 * set the flag FLAG_SCAN_ONLY_IF_RNR_FOUND for each remaining
+		 * channels.
+		 */
+		scm_add_all_valid_6g_channels(pdev, req, &num_scan_ch);
+		break;
 	default:
 		/*
 		 * Don't set the RNR flag for SCAN_MODE_6G_NO_CHANNEL/

+ 3 - 2
umac/scan/dispatcher/inc/wlan_scan_public_structs.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -1127,7 +1127,8 @@ struct scan_req_params {
 		struct {
 			uint32_t scan_policy_high_accuracy:1,
 				 scan_policy_low_span:1,
-				 scan_policy_low_power:1;
+				 scan_policy_low_power:1,
+				 scan_policy_colocated_6ghz:1;
 		};
 		uint32_t scan_policy_type;
 	};