Эх сурвалжийг харах

qcacmn: 6g scan optimizations based on the ini

Below optimizations can help to improve 6g scan,
1. RNR-only: Consider only 6g RNR(PSC and non-PSC) channels found
   while scanning 2g and 5g bands, as the 6g APs are likely to
   present in RNR channels.
2. Duty cycle: There is a chance to miss the standalone 6g APs as
   they don't advertise RNR IEs. So, instead of optimizing all
   scan requests, we can consider to do a full scan with duty
   cycle(n) where optimization is skipped for every nth full scan.
   The full scan requests 1 to n-1 are going to be optimized as
   per RNR-only policy.
Driver shall maintain a scan count to track the full scans and
decides whether to optimize the scan (scan count 1 to n-1) or
send it as it is(scan count n) to firmware.

Change-Id: I35b31e900b74dbcd7791f4c2fcfe87b3c629758b
CRs-Fixed: 2806409
Srinivas Dasari 4 жил өмнө
parent
commit
d7b3042685

+ 8 - 0
umac/scan/core/src/wlan_scan_main.h

@@ -327,6 +327,9 @@ struct extscan_def_config {
  * @max_active_scans_allowed: maximum number of active parallel scan allowed
  *                            per psoc
  * @scan_mode_6g: scan mode in 6Ghz
+ * @duty_cycle_6ghz: Enable optimization on 6g channels for every full scan
+ *                   except the duty cycle. So that every nth scan(depending on
+ *                   duty cycle) is a full scan and rest are all optimized scans
  * @enable_connected_scan: enable scans after connection
  * @scan_priority: default scan priority
  * @adaptive_dwell_time_mode: adaptive dwell mode with connection
@@ -414,6 +417,7 @@ struct scan_default_params {
 	uint8_t go_scan_burst_duration;
 	uint8_t ap_scan_burst_duration;
 	enum scan_mode_6ghz scan_mode_6g;
+	uint8_t duty_cycle_6ghz;
 	bool enable_connected_scan;
 	enum scan_priority scan_priority;
 	enum scan_dwelltime_adaptive_mode adaptive_dwell_time_mode;
@@ -506,6 +510,9 @@ struct scan_cb {
  * @scan_start_request_buff: buffer used to pass
  *      scan config to event handlers
  * @rnr_channel_db: RNR channel list database
+ * @duty_cycle_cnt_6ghz: Scan count to track the full scans and decide whether
+ *                        to optimizate 6g channels in the scan request based
+ *                        on the ini scan_mode_6ghz_duty_cycle.
  */
 struct wlan_scan_obj {
 	uint32_t scan_disabled;
@@ -539,6 +546,7 @@ struct wlan_scan_obj {
 	uint64_t scm_scan_event_duration;
 	uint64_t scm_scan_to_post_scan_duration;
 #endif
+	uint16_t duty_cycle_cnt_6ghz;
 };
 
 #ifdef ENABLE_SCAN_PROFILE

+ 8 - 6
umac/scan/core/src/wlan_scan_manager.c

@@ -1075,7 +1075,7 @@ static inline void scm_print_scan_req_info(struct scan_req_params *req)
 	uint32_t len = 0;
 	uint8_t idx, count = 0;
 	struct chan_list *chan_lst;
-#define MAX_SCAN_FREQ_TO_PRINT 60
+#define MAX_SCAN_FREQ_TO_PRINT 25
 
 	scm_nofl_debug("Scan start: scan id %d vdev %d Dwell time: act %d pass %d act_2G %d act_6G %d pass_6G %d, probe time %d n_probes %d flags %x ext_flag %x events %x policy %d wide_bw %d pri %d",
 		       req->scan_id, req->vdev_id, req->dwell_time_active,
@@ -1095,18 +1095,20 @@ static inline void scm_print_scan_req_info(struct scan_req_params *req)
 	if (!chan_lst->num_chan)
 		return;
 	/*
-	 * Buffer of (num channl * 5) + 1  to consider the 4 char freq and
-	 * 1 space after it for each channel and 1 to end the string with NULL.
+	 * Buffer of (num channl * 11) + 1  to consider the 4 char freq, 6 char
+	 * flags and 1 space after it for each channel and 1 to end the string
+	 * with NULL.
 	 */
 	buff_len =
-		(QDF_MIN(MAX_SCAN_FREQ_TO_PRINT, chan_lst->num_chan) * 5) + 1;
+		(QDF_MIN(MAX_SCAN_FREQ_TO_PRINT, chan_lst->num_chan) * 11) + 1;
 	chan_buff = qdf_mem_malloc(buff_len);
 	if (!chan_buff)
 		return;
 	scm_nofl_debug("Total freq %d", chan_lst->num_chan);
 	for (idx = 0; idx < chan_lst->num_chan; idx++) {
-		len += qdf_scnprintf(chan_buff + len, buff_len - len, "%d ",
-				     chan_lst->chan[idx].freq);
+		len += qdf_scnprintf(chan_buff + len, buff_len - len,
+				     "%d(0x%02x) ", chan_lst->chan[idx].freq,
+				     chan_lst->chan[idx].flags);
 		count++;
 		if (count >= MAX_SCAN_FREQ_TO_PRINT) {
 			/* Print the MAX_SCAN_FREQ_TO_PRINT channels */

+ 146 - 16
umac/scan/core/src/wlan_scan_manager_6ghz.c

@@ -90,8 +90,14 @@ scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
 		rnr_chan_info[j].weight = weight;
 		rnr_chan_info[j].chan_freq = temp_list[i].freq;
 		j++;
-		scm_debug("Freq %d weight %d bcn_cnt %d", temp_list[i].freq,
-			  weight, channel->bss_beacon_probe_count);
+		/*
+		 * Log the info only if weight or bss_beacon_probe_count are
+		 * non-zero to avoid excessive logging.
+		 */
+		if (weight || channel->bss_beacon_probe_count)
+			scm_debug("Freq %d weight %d bcn_cnt %d",
+				  temp_list[i].freq, weight,
+				  channel->bss_beacon_probe_count);
 	}
 
 	/* Sort the channel using selection sort - descending order */
@@ -217,12 +223,13 @@ scm_is_full_scan_by_userspace(struct chan_list *chan_list)
 }
 
 static void
-scm_copy_valid_channels(enum scan_mode_6ghz scan_mode,
+scm_copy_valid_channels(struct wlan_objmgr_psoc *psoc,
+			enum scan_mode_6ghz scan_mode,
 			struct chan_list *chan_list,
 			uint8_t *num_scan_ch)
 {
-	qdf_freq_t freq;
 	uint8_t i, num_ch = *num_scan_ch;
+	qdf_freq_t freq;
 
 	switch (scan_mode) {
 	case SCAN_MODE_6G_NO_CHANNEL:
@@ -234,21 +241,37 @@ scm_copy_valid_channels(enum scan_mode_6ghz scan_mode,
 					chan_list->chan[i];
 		break;
 	case SCAN_MODE_6G_PSC_CHANNEL:
-		/* Allow only PSC channels */
-		for (i = 0; i < chan_list->num_chan; i++) {
-			freq = chan_list->chan[i].freq;
-			if (!wlan_reg_is_6ghz_chan_freq(freq)) {
-				chan_list->chan[num_ch++] = chan_list->chan[i];
-				continue;
+	case SCAN_MODE_6G_PSC_DUTY_CYCLE:
+		/*
+		 * Don't add non-PSC 6g channels if firmware doesn't
+		 * support RNR_ONLY scan flag/feature.
+		 */
+		if (!scm_is_6ghz_scan_optimization_supported(psoc)) {
+			for (i = 0; i < chan_list->num_chan; i++) {
+				freq = chan_list->chan[i].freq;
+				if (!wlan_reg_is_6ghz_chan_freq(freq) ||
+				    (wlan_reg_is_6ghz_chan_freq(freq) &&
+				     wlan_reg_is_6ghz_psc_chan_freq(freq)))
+					chan_list->chan[num_ch++] =
+						chan_list->chan[i];
 			}
-			if (wlan_reg_is_6ghz_psc_chan_freq(freq))
-				chan_list->chan[num_ch++] = chan_list->chan[i];
+			break;
 		}
-		break;
+		/*
+		 * Consider the complete channel list if firmware supports
+		 * RNR_ONLY scan flag/feature.
+		 */
+
 	default:
 		/*
-		 * Allow all 2g/5g/6g channels.
-		 * SCAN_MODE_6G_ALL_CHANNEL is also covered in this
+		 * Allow all 2g/5g/6g channels. Below are also covered in this
+		 * 1. SCAN_MODE_6G_ALL_CHANNEL: Copy all channels and RNR flag
+		 *    won't be set for any channel.
+		 * 2. SCAN_MODE_6G_PSC_CHANNEL: Copy all channels and RNR flag
+		 *    will be set for non-PSC.
+		 * 3. SCAN_MODE_6G_PSC_DUTY_CYCLE: Copy all channels and RNR
+		 *    flag will be set for non-PSC for all scans and RNR flag
+		 *    will be set for PSC channels only for duty cycle scan.
 		 */
 		num_ch = chan_list->num_chan;
 	}
@@ -256,6 +279,59 @@ scm_copy_valid_channels(enum scan_mode_6ghz scan_mode,
 	*num_scan_ch = num_ch;
 }
 
+static inline void
+scm_set_rnr_flag_non_psc_6g_ch(struct chan_info *chan, uint8_t num_chan)
+{
+	uint8_t i;
+
+	for (i = 0; i < num_chan; i++)
+		if (wlan_reg_is_6ghz_chan_freq(chan[i].freq) &&
+		    !wlan_reg_is_6ghz_psc_chan_freq(chan[i].freq))
+			chan[i].flags = FLAG_SCAN_ONLY_IF_RNR_FOUND;
+}
+
+static inline void
+scm_set_rnr_flag_all_6g_ch(struct chan_info *chan, uint8_t num_chan)
+{
+	uint8_t i;
+
+	for (i = 0; i < num_chan; i++)
+		if (wlan_reg_is_6ghz_chan_freq(chan[i].freq))
+			chan[i].flags = FLAG_SCAN_ONLY_IF_RNR_FOUND;
+}
+
+static bool scm_is_duty_cycle_scan(struct wlan_scan_obj *scan_obj)
+{
+	bool duty_cycle = false;
+
+	scan_obj->duty_cycle_cnt_6ghz++;
+	if (scan_obj->duty_cycle_cnt_6ghz ==
+		scan_obj->scan_def.duty_cycle_6ghz) {
+		duty_cycle = true;
+		scan_obj->duty_cycle_cnt_6ghz = 0;
+	}
+
+	return duty_cycle;
+}
+
+inline bool
+scm_is_6ghz_scan_optimization_supported(struct wlan_objmgr_psoc *psoc)
+{
+	return wlan_psoc_nif_fw_ext_cap_get(psoc,
+					    WLAN_SOC_CEXT_SCAN_PER_CH_CONFIG);
+}
+
+static inline bool
+scm_is_sta_in_conneceted_state(struct wlan_objmgr_vdev *vdev)
+{
+	QDF_STATUS status = wlan_vdev_is_up(vdev);
+
+	if (QDF_IS_STATUS_SUCCESS(status))
+		return true;
+
+	return false;
+}
+
 void
 scm_update_6ghz_channel_list(struct scan_start_request *req,
 			     struct wlan_scan_obj *scan_obj)
@@ -291,7 +367,61 @@ scm_update_6ghz_channel_list(struct scan_start_request *req,
 	    scm_is_full_scan_by_userspace(chan_list))
 		scm_add_rnr_info(pdev, req);
 
-	scm_copy_valid_channels(scan_mode, chan_list, &num_scan_ch);
+	/* copy all the channels given by userspace */
+	scm_copy_valid_channels(wlan_pdev_get_psoc(pdev), scan_mode, chan_list,
+				&num_scan_ch);
+
+	/* No more optimizations are needed in the below cases */
+	if (!scm_is_full_scan_by_userspace(chan_list) ||
+	    !scm_is_6ghz_scan_optimization_supported(
+				wlan_pdev_get_psoc(pdev)))
+		goto end;
+
+	switch (scan_mode) {
+	case SCAN_MODE_6G_RNR_ONLY:
+		/*
+		 * When the ini is set to SCAN_MODE_6G_RNR_ONLY,
+		 * always(connected/disconnected state) set RNR flag for
+		 * all(PSC and non-PSC) channels.
+		 */
+		scm_set_rnr_flag_all_6g_ch(&chan_list->chan[0], num_scan_ch);
+		break;
+	case SCAN_MODE_6G_PSC_CHANNEL:
+		/*
+		 * When the ini is set to SCAN_MODE_6G_PSC_CHANNEL,
+		 * always(connected/disconnected state) set RNR flag for
+		 * non-PSC channels.
+		 */
+		scm_set_rnr_flag_non_psc_6g_ch(&chan_list->chan[0],
+					       num_scan_ch);
+		break;
+	case SCAN_MODE_6G_PSC_DUTY_CYCLE:
+	case SCAN_MODE_6G_ALL_DUTY_CYCLE:
+		/*
+		 * When the ini is set to SCAN_MODE_6G_PSC_DUTY_CYCLE/
+		 * SCAN_MODE_6G_ALL_DUTY_CYCLE, set RNR flag only in
+		 * disconnected state. Connected scan is going to be a split
+		 * scan and no need to optimize the scan time.
+		 */
+		if (scm_is_sta_in_conneceted_state(vdev))
+			break;
+
+		if (!scm_is_duty_cycle_scan(scan_obj))
+			scm_set_rnr_flag_all_6g_ch(&chan_list->chan[0],
+						   num_scan_ch);
+		else if (scan_mode == SCAN_MODE_6G_PSC_DUTY_CYCLE)
+			scm_set_rnr_flag_non_psc_6g_ch(&chan_list->chan[0],
+						       num_scan_ch);
+		break;
+	default:
+		/*
+		 * Don't set the RNR flag for SCAN_MODE_6G_NO_CHANNEL/
+		 * SCAN_MODE_6G_RNR_ONLY
+		 */
+		break;
+	}
+
+end:
 	chan_list->num_chan = num_scan_ch;
 
 	scm_sort_6ghz_channel_list(req->vdev, &req->scan_req.chan_list);

+ 25 - 0
umac/scan/core/src/wlan_scan_manager_6ghz.h

@@ -38,6 +38,14 @@
  */
 #define FULL_SCAN_CH_COUNT_MIN_BY_USERSPACE 11
 
+/*
+ * This can used to set the RNR_ONLY flag to certain type(PSC/non-PSC) or
+ * all channels.
+ */
+#define SET_RNR_FLAG_TO_PSC_CHANNEL 0x1
+#define SET_RNR_FLAG_TO_NON_PSC_CHANNEL 0x2
+#define SET_RNR_FLAG_TO_ALL_6G_CHANNELS 0x3
+
 /**
  * scm_update_6ghz_channel_list() - Update 6ghz channel list in the scan req
  * @req: scan start request
@@ -51,12 +59,29 @@
 void
 scm_update_6ghz_channel_list(struct scan_start_request *req,
 			     struct wlan_scan_obj *scan_obj);
+
+/**
+ * scm_is_6ghz_scan_optimization_supported() - Check firmware capability
+ * @psoc: psoc
+ *
+ * Check if firmware supports 6ghz scan optimization from fw_ext_caps of psoc.
+ *
+ * Return: None
+ */
+bool
+scm_is_6ghz_scan_optimization_supported(struct wlan_objmgr_psoc *psoc);
 #else
 static inline void
 scm_update_6ghz_channel_list(struct scan_start_request *req,
 			     struct wlan_scan_obj *scan_obj)
 {
 }
+
+static inline bool
+scm_is_6ghz_scan_optimization_supported(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
 #endif
 
 #endif

+ 9 - 0
umac/scan/dispatcher/inc/wlan_scan_public_structs.h

@@ -691,14 +691,23 @@ struct probe_req_whitelist_attr {
 	uint32_t voui[MAX_PROBE_REQ_OUIS];
 };
 
+/**
+ * Set this flag for a 6g channel to scan it only if an RNR IE is found
+ * with that channel while scanning 2g/5g bands
+ */
+#define FLAG_SCAN_ONLY_IF_RNR_FOUND 0x1
+
 /**
  * struct chan_info - channel information
  * @freq: frequency to scan
  * @phymode: phymode in which @frequency should be scanned
+ * @flags: Flags to define channel property. Firmware can use this info for
+ *  different operations, e.g.: scan
  */
 struct chan_info {
 	qdf_freq_t freq;
 	uint32_t phymode;
+	uint8_t flags;
 };
 
 /**

+ 2 - 0
umac/scan/dispatcher/src/wlan_scan_ucfg_api.c

@@ -836,6 +836,8 @@ wlan_scan_global_init(struct wlan_objmgr_psoc *psoc,
 	scan_obj->scan_def.enable_connected_scan =
 		cfg_get(psoc, CFG_ENABLE_CONNECTED_SCAN);
 	scan_obj->scan_def.scan_mode_6g = cfg_get(psoc, CFG_6GHZ_SCAN_MODE);
+	scan_obj->scan_def.duty_cycle_6ghz =
+		cfg_get(psoc, CFG_6GHZ_SCAN_MODE_DUTY_CYCLE);
 	/* init scan id seed */
 	qdf_atomic_init(&scan_obj->scan_ids);
 

+ 19 - 2
wmi/src/wmi_unified_tlv.c

@@ -64,6 +64,19 @@
 #include <wmi_unified_vdev_api.h>
 #include <wmi_unified_vdev_tlv.h>
 
+/*
+ * If FW supports WMI_SERVICE_SCAN_CONFIG_PER_CHANNEL,
+ * then channel_list may fill the upper 12 bits with channel flags,
+ * while using only the lower 20 bits for channel frequency.
+ * If FW doesn't support WMI_SERVICE_SCAN_CONFIG_PER_CHANNEL,
+ * then channel_list only holds the frequency value.
+ */
+#define CHAN_LIST_FLAG_MASK_POS 20
+#define TARGET_SET_FREQ_IN_CHAN_LIST_TLV(buf, freq) \
+			((buf) |= ((freq) & WMI_SCAN_CHANNEL_FREQ_MASK))
+#define TARGET_SET_FLAGS_IN_CHAN_LIST_TLV(buf, flags) \
+			((buf) |= ((flags) << CHAN_LIST_FLAG_MASK_POS))
+
 /* HTC service ids for WMI for multi-radio */
 static const uint32_t multi_svc_ids[] = {WMI_CONTROL_SVC,
 				WMI_CONTROL_SVC_WMAC1,
@@ -2974,8 +2987,12 @@ static QDF_STATUS send_scan_start_cmd_tlv(wmi_unified_t wmi_handle,
 
 	buf_ptr += sizeof(*cmd);
 	tmp_ptr = (uint32_t *) (buf_ptr + WMI_TLV_HDR_SIZE);
-	for (i = 0; i < params->chan_list.num_chan; ++i)
-		tmp_ptr[i] = params->chan_list.chan[i].freq;
+	for (i = 0; i < params->chan_list.num_chan; ++i) {
+		TARGET_SET_FREQ_IN_CHAN_LIST_TLV(tmp_ptr[i],
+					params->chan_list.chan[i].freq);
+		TARGET_SET_FLAGS_IN_CHAN_LIST_TLV(tmp_ptr[i],
+					params->chan_list.chan[i].flags);
+	}
 
 	WMITLV_SET_HDR(buf_ptr,
 		       WMITLV_TAG_ARRAY_UINT32,