瀏覽代碼

qcacmn: Support for history based scan request

Userspace/framework tracks last few days(e.g: 10 days) history of
connected APs and maintains best 10 channels out of that list by
considering multiple parameters like scoring, location etc.
It's likely to find an AP in one of these channels when a scan issued.
So, framework issues first scan request with a maximum of 10 channels
in the below cases currently,
1. When the wifi is turned on
2. When the wifi is in disconnected state and user turns on the screen.

Host driver shouldn't add any more channels to this scan request as
it's expected to complete the scan as soon as possible to connect
quickly to the known APs. Don't add 6g RNR channels also in the
scan request.
Further scans from framework would be full scans or with list a
of channels(more than 10) and RNR channels can be added to them.

Also, don't add all 6g channels if userspace hasn't given any as
the current framework/kernels are matured enough decide whether to
issue scan with 6g channels or not. RNR channels can be added as
mentioned. Remove SCAN_MODE_6G_NO_OPERATION as it's not needed
anymore with this.

Also, 6ghz scan functionality gets enahanced depending on various
requirements. This can be moved to a separate file so that core
scan_manager.c file won't be bloated with new code.

Change-Id: I1800a3e95e438720f94d8eec3544023cab16b081
CRs-Fixed: 2805900
Srinivas Dasari 4 年之前
父節點
當前提交
bac5be8a23

+ 2 - 286
umac/scan/core/src/wlan_scan_manager.c

@@ -36,18 +36,6 @@
 #include <wlan_dfs_utils_api.h>
 #include <wlan_scan_cfg.h>
 
-/* Beacon/probe weightage multiplier */
-#define BCN_PROBE_WEIGHTAGE 5
-
-/* Saved profile weightage multiplier */
-#define SAVED_PROFILE_WEIGHTAGE 10
-
-/* maximum number of 6ghz hints can be sent per scan request */
-#define MAX_HINTS_PER_SCAN_REQ 15
-
-/* maximum number of hints can be sent per 6ghz channel */
-#define MAX_HINTS_PER_CHANNEL 4
-
 QDF_STATUS
 scm_scan_free_scan_request_mem(struct scan_start_request *req)
 {
@@ -865,259 +853,6 @@ static inline void scm_scan_chlist_concurrency_modify(
 }
 #endif
 
-#ifdef CONFIG_BAND_6GHZ
-static void
-scm_update_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
-			     struct chan_list *chan_list,
-			     struct wlan_scan_obj *scan_obj)
-{
-	uint8_t i;
-	struct regulatory_channel *chan_list_6g;
-	bool psc_channel_found = false;
-	bool channel_6g_found = false;
-	uint8_t num_scan_channels = 0, channel_count;
-	struct wlan_objmgr_pdev *pdev;
-	uint32_t freq;
-
-	pdev = wlan_vdev_get_pdev(vdev);
-	if (!pdev)
-		return;
-
-	scm_debug("6g scan mode %d", scan_obj->scan_def.scan_mode_6g);
-	for (i = 0; i < chan_list->num_chan; i++) {
-		freq = chan_list->chan[i].freq;
-		if ((scan_obj->scan_def.scan_mode_6g ==
-		     SCAN_MODE_6G_NO_CHANNEL) &&
-		    (wlan_reg_is_6ghz_chan_freq(freq))) {
-			/* Drop the 6Ghz channels */
-			continue;
-		} else if ((scan_obj->scan_def.scan_mode_6g ==
-			SCAN_MODE_6G_PSC_CHANNEL) &&
-			(wlan_reg_is_6ghz_chan_freq(freq))) {
-			/* Allow only PSC channels */
-			if (wlan_reg_is_6ghz_psc_chan_freq(freq))
-				psc_channel_found = true;
-			else
-				continue;
-		} else if ((scan_obj->scan_def.scan_mode_6g ==
-			     SCAN_MODE_6G_ALL_CHANNEL) &&
-			    (wlan_reg_is_6ghz_chan_freq(freq))) {
-			/* Allow  any 6ghz channel */
-			channel_6g_found = true;
-		}
-		chan_list->chan[num_scan_channels++] =
-			chan_list->chan[i];
-	}
-
-	scm_debug("psc_channel_found %d channel_6g_found%d",
-		  psc_channel_found, channel_6g_found);
-	if ((scan_obj->scan_def.scan_mode_6g == SCAN_MODE_6G_PSC_CHANNEL &&
-	     !psc_channel_found) ||
-	    (scan_obj->scan_def.scan_mode_6g == SCAN_MODE_6G_ALL_CHANNEL &&
-	     !channel_6g_found)) {
-		chan_list_6g = qdf_mem_malloc(NUM_6GHZ_CHANNELS *
-				sizeof(struct regulatory_channel));
-		if (!chan_list_6g)
-			goto end;
-
-		/* Add the 6Ghz channels based on config*/
-		channel_count = wlan_reg_get_band_channel_list(pdev,
-							       BIT(REG_BAND_6G),
-							       chan_list_6g);
-		scm_debug("Number of 6G channels %d", channel_count);
-		for (i = 0; i < channel_count; i++) {
-			if ((scan_obj->scan_def.scan_mode_6g ==
-			     SCAN_MODE_6G_PSC_CHANNEL) &&
-			     (!psc_channel_found) &&
-			     wlan_reg_is_6ghz_psc_chan_freq(chan_list_6g[i].
-				center_freq)) {
-				chan_list->chan[num_scan_channels++].freq =
-					chan_list_6g[i].center_freq;
-			} else if ((scan_obj->scan_def.scan_mode_6g ==
-			     SCAN_MODE_6G_ALL_CHANNEL) &&
-			    (!channel_6g_found)) {
-				chan_list->chan[num_scan_channels++].freq =
-					chan_list_6g[i].center_freq;
-			}
-		}
-		qdf_mem_free(chan_list_6g);
-	}
-end:
-	chan_list->num_chan = num_scan_channels;
-}
-#else
-static void
-scm_update_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
-			     struct chan_list *chan_list,
-			     struct wlan_scan_obj *scan_obj)
-{
-}
-#endif
-
-#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
-static void scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
-				       struct chan_list *chan_list)
-{
-	uint8_t i, j = 0, max, tmp_list_count;
-	struct meta_rnr_channel *channel;
-	struct chan_info temp_list[MAX_6GHZ_CHANNEL];
-	struct rnr_chan_weight *rnr_chan_info, *temp;
-	uint32_t weight;
-	struct wlan_objmgr_psoc *psoc;
-
-	rnr_chan_info = qdf_mem_malloc(sizeof(rnr_chan_info) * MAX_6GHZ_CHANNEL);
-	if (!rnr_chan_info)
-		return;
-
-	for (i = 0; i < chan_list->num_chan; i++) {
-		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_list->chan[i].freq))
-			temp_list[j++].freq = chan_list->chan[i].freq;
-	}
-	tmp_list_count = j;
-	scm_debug("Total 6ghz channels %d", tmp_list_count);
-
-	/* No Need to sort if the 6ghz channels are less than one */
-	if (tmp_list_count < 1) {
-		qdf_mem_free(rnr_chan_info);
-		return;
-	}
-
-	psoc = wlan_vdev_get_psoc(vdev);
-	if (!psoc) {
-		scm_err("Psoc is NULL");
-		qdf_mem_free(rnr_chan_info);
-		return;
-	}
-
-	/* compute the weightage */
-	for (i = 0, j = 0; i < tmp_list_count; i++) {
-		channel = scm_get_chan_meta(psoc, temp_list[i].freq);
-		if (!channel)
-			continue;
-		weight = channel->bss_beacon_probe_count * BCN_PROBE_WEIGHTAGE +
-			 channel->saved_profile_count * SAVED_PROFILE_WEIGHTAGE;
-		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);
-	}
-
-	/* Sort the channel using selection sort - descending order */
-	for (i = 0; i < tmp_list_count - 1; i++) {
-		max = i;
-		for (j = i + 1; j < tmp_list_count; j++) {
-			if (rnr_chan_info[j].weight >
-			    rnr_chan_info[max].weight)
-				max = j;
-		}
-		if (max != i) {
-			qdf_mem_copy(&temp, &rnr_chan_info[max],
-				     sizeof(*rnr_chan_info));
-			qdf_mem_copy(&rnr_chan_info[max], &rnr_chan_info[i],
-				     sizeof(*rnr_chan_info));
-			qdf_mem_copy(&rnr_chan_info[i], &temp,
-				     sizeof(*rnr_chan_info));
-		}
-	}
-
-	/* update the 6g list based on the weightage */
-	for (i = 0, j = 0; (i < NUM_CHANNELS && j < tmp_list_count); i++) {
-		if (wlan_reg_is_6ghz_chan_freq(chan_list->chan[i].freq))
-			chan_list->chan[i].freq = rnr_chan_info[j++].chan_freq;
-	}
-	qdf_mem_free(rnr_chan_info);
-}
-
-static void scm_update_rnr_info(struct wlan_objmgr_psoc *psoc,
-				struct scan_start_request *req)
-{
-	uint8_t i, num_bssid = 0, num_ssid = 0;
-	uint8_t total_count = MAX_HINTS_PER_SCAN_REQ;
-	uint32_t freq;
-	struct meta_rnr_channel *chan;
-	qdf_list_node_t *cur_node, *next_node = NULL;
-	struct scan_rnr_node *rnr_node;
-	struct chan_list *chan_list;
-	QDF_STATUS status;
-
-	if (!req)
-		return;
-
-	chan_list = &req->scan_req.chan_list;
-	for (i = 0; i < chan_list->num_chan; i++) {
-		freq = chan_list->chan[i].freq;
-
-		chan = scm_get_chan_meta(psoc, freq);
-		if (!chan || qdf_list_empty(&chan->rnr_list))
-			continue;
-
-		qdf_list_peek_front(&chan->rnr_list, &cur_node);
-		while (cur_node && total_count) {
-			rnr_node = qdf_container_of(cur_node,
-						    struct scan_rnr_node,
-						    node);
-			if (!qdf_is_macaddr_zero(&rnr_node->entry.bssid) &&
-			    req->scan_req.num_hint_bssid <
-			    WLAN_SCAN_MAX_HINT_BSSID) {
-				qdf_mem_copy(&req->scan_req.hint_bssid[num_bssid++].bssid,
-					     &rnr_node->entry.bssid,
-					     QDF_MAC_ADDR_SIZE);
-				req->scan_req.num_hint_bssid++;
-				total_count--;
-			} else if (rnr_node->entry.short_ssid &&
-				   req->scan_req.num_hint_s_ssid <
-				   WLAN_SCAN_MAX_HINT_S_SSID) {
-				req->scan_req.hint_s_ssid[num_ssid++].short_ssid =
-						rnr_node->entry.short_ssid;
-				req->scan_req.num_hint_s_ssid++;
-				total_count--;
-			}
-			status = qdf_list_peek_next(&chan->rnr_list, cur_node,
-						    &next_node);
-			if (QDF_IS_STATUS_ERROR(status))
-				break;
-			cur_node = next_node;
-			next_node = NULL;
-		}
-	}
-}
-
-static void scm_add_rnr_info(struct wlan_objmgr_pdev *pdev,
-			     struct scan_start_request *req)
-{
-	struct wlan_objmgr_psoc *psoc;
-	struct channel_list_db *rnr_db;
-
-	psoc = wlan_pdev_get_psoc(pdev);
-	if (!psoc)
-		return;
-	rnr_db = scm_get_rnr_channel_db(psoc);
-	if (!rnr_db)
-		return;
-
-	rnr_db->scan_count++;
-	if (rnr_db->scan_count >= RNR_UPDATE_SCAN_CNT_THRESHOLD) {
-		rnr_db->scan_count = 0;
-		scm_rnr_db_flush(psoc);
-		scm_update_rnr_from_scan_cache(pdev);
-	}
-
-	scm_update_rnr_info(psoc, req);
-}
-
-#else
-static void scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
-				       struct chan_list *chan_list)
-{
-}
-
-static void scm_add_rnr_info(struct wlan_objmgr_pdev *pdev,
-			     struct scan_start_request *req)
-{
-}
-#endif
-
 /**
  * scm_update_channel_list() - update scan req params depending on dfs inis
  * and initial scan request.
@@ -1138,7 +873,6 @@ scm_update_channel_list(struct scan_start_request *req,
 	bool p2p_search = false;
 	bool skip_dfs_ch = true;
 	uint32_t first_freq;
-	enum QDF_OPMODE op_mode;
 
 	pdev = wlan_vdev_get_pdev(req->vdev);
 
@@ -1198,21 +932,8 @@ scm_update_channel_list(struct scan_start_request *req,
 	}
 
 	req->scan_req.chan_list.num_chan = num_scan_channels;
-	/* Dont update the channel list:
-	 * - if not STA mode and
-	 * - if scan mode is set to SCAN_MODE_6G_NO_OPERATION
-	 */
-	op_mode = wlan_vdev_mlme_get_opmode(req->vdev);
-	if (op_mode != QDF_SAP_MODE &&
-	    op_mode != QDF_P2P_DEVICE_MODE &&
-	    op_mode != QDF_P2P_CLIENT_MODE &&
-	    op_mode != QDF_P2P_GO_MODE &&
-	    scan_obj->scan_def.scan_mode_6g != SCAN_MODE_6G_NO_OPERATION) {
-		scm_update_6ghz_channel_list(req->vdev,
-					     &req->scan_req.chan_list,
-					     scan_obj);
-		scm_sort_6ghz_channel_list(req->vdev, &req->scan_req.chan_list);
-	}
+
+	scm_update_6ghz_channel_list(req, scan_obj);
 	scm_scan_chlist_concurrency_modify(req->vdev, req);
 }
 
@@ -1233,7 +954,6 @@ scm_scan_req_update_params(struct wlan_objmgr_vdev *vdev,
 	struct chan_list *custom_chan_list;
 	struct wlan_objmgr_pdev *pdev;
 	uint8_t pdev_id;
-	enum QDF_OPMODE op_mode;
 
 	/* Ensure correct number of probes are sent on active channel */
 	if (!req->scan_req.repeat_probe_time)
@@ -1345,10 +1065,6 @@ scm_scan_req_update_params(struct wlan_objmgr_vdev *vdev,
 	else if (!req->scan_req.chan_list.num_chan)
 		ucfg_scan_init_chanlist_params(req, 0, NULL, NULL);
 
-	op_mode = wlan_vdev_mlme_get_opmode(vdev);
-	if (scan_obj->scan_def.scan_mode_6g != SCAN_MODE_6G_NO_CHANNEL &&
-	    op_mode == QDF_STA_MODE)
-		scm_add_rnr_info(pdev, req);
 	scm_update_channel_list(req, scan_obj);
 }
 

+ 1 - 0
umac/scan/core/src/wlan_scan_manager.h

@@ -27,6 +27,7 @@
 #define _WLAN_SCAN_MANAGER_API_H_
 
 #include "wlan_scan_main.h"
+#include "wlan_scan_manager_6ghz.h"
 
 /**
  * struct scan_event_listners - listeners interested in a particular scan event

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

@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2017-2020 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * DOC: contains 6ghz scan manager functionality
+ */
+
+#include "wlan_scan_main.h"
+#include "wlan_utility.h"
+#include <wlan_reg_services_api.h>
+#include "wlan_scan_manager.h"
+
+/* Beacon/probe weightage multiplier */
+#define BCN_PROBE_WEIGHTAGE 5
+
+/* maximum number of 6ghz hints can be sent per scan request */
+#define MAX_HINTS_PER_SCAN_REQ 15
+
+/* Saved profile weightage multiplier */
+#define SAVED_PROFILE_WEIGHTAGE 10
+
+#ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
+
+/**
+ * scm_sort_6ghz_channel_list() - Sort the 6ghz channels based on weightage
+ * @vdev: vdev on which scan request is issued
+ * @chan_list: channel info of the scan request
+ *
+ * Calculate weightage of each channel based on beacon weightage and saved
+ * profile weightage. Sort the channels based on this weight in descending order
+ * to scan the most preferred channels first compared other 6ghz channels.
+ *
+ * Return: None
+ */
+static void
+scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
+			   struct chan_list *chan_list)
+{
+	uint8_t i, j = 0, max, tmp_list_count;
+	struct meta_rnr_channel *channel;
+	struct chan_info temp_list[MAX_6GHZ_CHANNEL];
+	struct rnr_chan_weight *rnr_chan_info, *temp;
+	uint32_t weight;
+	struct wlan_objmgr_psoc *psoc;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		scm_err("Psoc is NULL");
+		return;
+	}
+
+	for (i = 0; i < chan_list->num_chan; i++)
+		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_list->chan[i].freq))
+			temp_list[j++].freq = chan_list->chan[i].freq;
+
+	tmp_list_count = j;
+	scm_debug("Total 6ghz channels %d", tmp_list_count);
+
+	/* No Need to sort if the 6ghz channels are less than or one */
+	if (tmp_list_count <= 1)
+		return;
+
+	rnr_chan_info =
+		qdf_mem_malloc(sizeof(rnr_chan_info) * MAX_6GHZ_CHANNEL);
+	if (!rnr_chan_info)
+		return;
+
+	/* compute the weightage */
+	for (i = 0, j = 0; i < tmp_list_count; i++) {
+		channel = scm_get_chan_meta(psoc, temp_list[i].freq);
+		if (!channel)
+			continue;
+		weight = channel->bss_beacon_probe_count * BCN_PROBE_WEIGHTAGE +
+			 channel->saved_profile_count * SAVED_PROFILE_WEIGHTAGE;
+		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);
+	}
+
+	/* Sort the channel using selection sort - descending order */
+	for (i = 0; i < tmp_list_count - 1; i++) {
+		max = i;
+		for (j = i + 1; j < tmp_list_count; j++) {
+			if (rnr_chan_info[j].weight >
+			    rnr_chan_info[max].weight)
+				max = j;
+		}
+		if (max != i) {
+			qdf_mem_copy(&temp, &rnr_chan_info[max],
+				     sizeof(*rnr_chan_info));
+			qdf_mem_copy(&rnr_chan_info[max], &rnr_chan_info[i],
+				     sizeof(*rnr_chan_info));
+			qdf_mem_copy(&rnr_chan_info[i], &temp,
+				     sizeof(*rnr_chan_info));
+		}
+	}
+
+	/* update the 6g list based on the weightage */
+	for (i = 0, j = 0; (i < NUM_CHANNELS && j < tmp_list_count); i++)
+		if (wlan_reg_is_6ghz_chan_freq(chan_list->chan[i].freq))
+			chan_list->chan[i].freq = rnr_chan_info[j++].chan_freq;
+
+	qdf_mem_free(rnr_chan_info);
+}
+
+static void scm_update_rnr_info(struct wlan_objmgr_psoc *psoc,
+				struct scan_start_request *req)
+{
+	uint8_t i, num_bssid = 0, num_ssid = 0;
+	uint8_t total_count = MAX_HINTS_PER_SCAN_REQ;
+	uint32_t freq;
+	struct meta_rnr_channel *chan;
+	qdf_list_node_t *cur_node, *next_node = NULL;
+	struct scan_rnr_node *rnr_node;
+	struct chan_list *chan_list;
+	QDF_STATUS status;
+
+	if (!req)
+		return;
+
+	chan_list = &req->scan_req.chan_list;
+	for (i = 0; i < chan_list->num_chan; i++) {
+		freq = chan_list->chan[i].freq;
+
+		chan = scm_get_chan_meta(psoc, freq);
+		if (!chan || qdf_list_empty(&chan->rnr_list))
+			continue;
+
+		qdf_list_peek_front(&chan->rnr_list, &cur_node);
+		while (cur_node && total_count) {
+			rnr_node = qdf_container_of(cur_node,
+						    struct scan_rnr_node,
+						    node);
+			if (!qdf_is_macaddr_zero(&rnr_node->entry.bssid) &&
+			    req->scan_req.num_hint_bssid <
+			    WLAN_SCAN_MAX_HINT_BSSID) {
+				qdf_mem_copy(&req->scan_req.hint_bssid[
+							num_bssid++].bssid,
+					     &rnr_node->entry.bssid,
+					     QDF_MAC_ADDR_SIZE);
+				req->scan_req.num_hint_bssid++;
+				total_count--;
+			} else if (rnr_node->entry.short_ssid &&
+				   req->scan_req.num_hint_s_ssid <
+				   WLAN_SCAN_MAX_HINT_S_SSID) {
+				req->scan_req.hint_s_ssid[
+					num_ssid++].short_ssid =
+						rnr_node->entry.short_ssid;
+				req->scan_req.num_hint_s_ssid++;
+				total_count--;
+			}
+			status = qdf_list_peek_next(&chan->rnr_list, cur_node,
+						    &next_node);
+			if (QDF_IS_STATUS_ERROR(status))
+				break;
+			cur_node = next_node;
+			next_node = NULL;
+		}
+	}
+}
+
+/**
+ * scm_add_rnr_info() - Add the cached RNR info to scan request
+ * @vdev: vdev on which scan request is issued
+ * @req: Scan start request
+ *
+ * Fetch the cached RNR info from scan db and update it to the scan request to
+ * include RNR channels in the scan request.
+ *
+ * Return: None
+ */
+static void scm_add_rnr_info(struct wlan_objmgr_pdev *pdev,
+			     struct scan_start_request *req)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct channel_list_db *rnr_db;
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc)
+		return;
+	rnr_db = scm_get_rnr_channel_db(psoc);
+	if (!rnr_db)
+		return;
+
+	rnr_db->scan_count++;
+	if (rnr_db->scan_count >= RNR_UPDATE_SCAN_CNT_THRESHOLD) {
+		rnr_db->scan_count = 0;
+		scm_rnr_db_flush(psoc);
+		scm_update_rnr_from_scan_cache(pdev);
+	}
+
+	scm_update_rnr_info(psoc, req);
+}
+#endif
+
+static inline bool
+scm_is_full_scan_by_userspace(struct chan_list *chan_list)
+{
+	return (chan_list->num_chan >= FULL_SCAN_CH_COUNT_MIN_BY_USERSPACE);
+}
+
+static void
+scm_copy_valid_channels(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;
+
+	switch (scan_mode) {
+	case SCAN_MODE_6G_NO_CHANNEL:
+		/* Don't add any 6g channels */
+		for (i = 0; i < chan_list->num_chan; i++)
+			if (!wlan_reg_is_6ghz_chan_freq(
+					chan_list->chan[i].freq))
+				chan_list->chan[num_ch++] =
+					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;
+			}
+			if (wlan_reg_is_6ghz_psc_chan_freq(freq))
+				chan_list->chan[num_ch++] = chan_list->chan[i];
+		}
+		break;
+	default:
+		/*
+		 * Allow all 2g/5g/6g channels.
+		 * SCAN_MODE_6G_ALL_CHANNEL is also covered in this
+		 */
+		num_ch = chan_list->num_chan;
+	}
+
+	*num_scan_ch = num_ch;
+}
+
+void
+scm_update_6ghz_channel_list(struct scan_start_request *req,
+			     struct wlan_scan_obj *scan_obj)
+{
+	struct wlan_objmgr_vdev *vdev = req->vdev;
+	struct wlan_objmgr_pdev *pdev;
+	struct chan_list *chan_list = &req->scan_req.chan_list;
+	enum scan_mode_6ghz scan_mode;
+	uint8_t num_scan_ch = 0;
+	enum QDF_OPMODE op_mode;
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev)
+		return;
+
+	/* Dont update the channel list for not STA mode */
+	op_mode = wlan_vdev_mlme_get_opmode(req->vdev);
+	if (op_mode == QDF_SAP_MODE ||
+	    op_mode == QDF_P2P_DEVICE_MODE ||
+	    op_mode == QDF_P2P_CLIENT_MODE ||
+	    op_mode == QDF_P2P_GO_MODE)
+		return;
+
+	scan_mode = scan_obj->scan_def.scan_mode_6g;
+	scm_debug("6g scan mode %d", scan_mode);
+
+	/*
+	 * Host has learned RNR info/channels from previous scan. Add them to
+	 * the scan request and don't set RNR_ONLY flag to scan them without
+	 * optimization.
+	 */
+	if (scan_mode != SCAN_MODE_6G_NO_CHANNEL &&
+	    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);
+	chan_list->num_chan = num_scan_ch;
+
+	scm_sort_6ghz_channel_list(req->vdev, &req->scan_req.chan_list);
+}

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

@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017-2020 The Linux Foundation. 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * DOC: contains scan manager functionality
+ */
+
+#ifndef _WLAN_SCAN_MANAGER_6GHZ_API_H_
+#define _WLAN_SCAN_MANAGER_6GHZ_API_H_
+
+#include "wlan_scan_main.h"
+
+#ifdef CONFIG_BAND_6GHZ
+
+/*
+ * Userspace/framework tracks last few days(e.g: 10 days) history of
+ * connected APs and maintains best 10 channels out of that list by
+ * considering multiple parameters like scoring, location etc.
+ * It's likely to find an AP in one of these channels when a scan issued.
+ * So, framework issues first scan request with a maximum of 10 channels
+ * Any scan request which consist of more than 10 channels can be considered as
+ * full scan
+ */
+#define FULL_SCAN_CH_COUNT_MIN_BY_USERSPACE 11
+
+/**
+ * scm_update_6ghz_channel_list() - Update 6ghz channel list in the scan req
+ * @req: scan start request
+ * @scan_obj: scan component object
+ *
+ * Filter out the unsupported 6ghz channels from scan request and add supported
+ * 6ghz channels based on the ini.
+ *
+ * Return: None
+ */
+void
+scm_update_6ghz_channel_list(struct scan_start_request *req,
+			     struct wlan_scan_obj *scan_obj);
+#else
+static inline void
+scm_update_6ghz_channel_list(struct scan_start_request *req,
+			     struct wlan_scan_obj *scan_obj)
+{
+}
+#endif
+
+#endif

+ 2 - 5
umac/scan/dispatcher/inc/wlan_scan_cfg.h

@@ -29,14 +29,12 @@
  * @SCAN_MODE_6G_NO_CHANNEL: Remove 6GHz channels in the scan request
  * @SCAN_MODE_6G_PSC_CHANNEL: Allow/Add 6Ghz PSC channels to scan request
  * @SCAN_MODE_6G_ALL_CHANNEL: Allow all the 6Ghz channels
- * @SCAN_MODE_6G_NO_OPERATION: Don't perform any action keep channel list as is
  */
 enum scan_mode_6ghz {
 	SCAN_MODE_6G_NO_CHANNEL,
 	SCAN_MODE_6G_PSC_CHANNEL,
 	SCAN_MODE_6G_ALL_CHANNEL,
-	SCAN_MODE_6G_NO_OPERATION,
-	SCAN_MODE_6G_MAX = SCAN_MODE_6G_NO_OPERATION,
+	SCAN_MODE_6G_MAX = SCAN_MODE_6G_ALL_CHANNEL,
 };
 
 /*
@@ -1204,14 +1202,13 @@ enum scan_mode_6ghz {
  * <ini>
  * scan_mode_6ghz - 6ghz Scan mode
  * @Min: 0
- * @Max: 3
+ * @Max: 2
  * @Default: 1
  *
  * Configure the 6Ghz scan mode
  * 0 - Remove 6GHz channels in the scan request
  * 1 - Allow/Add 6Ghz PSC channels to scan request
  * 2 - Allow all the 6Ghz channels
- * 3 - Don't perform any action keep channel list as is
  *
  * Related: SCAN
  *