xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_manager_6ghz.c (revision 70a19e16789e308182f63b15c75decec7bf0b342)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * DOC: contains 6ghz scan manager functionality
22  */
23 
24 #include "wlan_scan_main.h"
25 #include "wlan_utility.h"
26 #include <wlan_reg_services_api.h>
27 #include "wlan_scan_manager.h"
28 
29 /* Beacon/probe weightage multiplier */
30 #define BCN_PROBE_WEIGHTAGE 5
31 
32 /* maximum number of 6ghz hints can be sent per scan request */
33 #define MAX_HINTS_PER_SCAN_REQ 15
34 
35 /* Saved profile weightage multiplier */
36 #define SAVED_PROFILE_WEIGHTAGE 10
37 
38 #ifdef CONFIG_BAND_6GHZ
39 #ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
40 
41 /**
42  * scm_sort_6ghz_channel_list() - Sort the 6ghz channels based on weightage
43  * @vdev: vdev on which scan request is issued
44  * @chan_list: channel info of the scan request
45  *
46  * Calculate weightage of each channel based on beacon weightage and saved
47  * profile weightage. Sort the channels based on this weight in descending order
48  * to scan the most preferred channels first compared other 6ghz channels.
49  *
50  * Return: None
51  */
52 static void
53 scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
54 			   struct chan_list *chan_list)
55 {
56 	uint8_t i, j = 0, max, tmp_list_count;
57 	struct meta_rnr_channel *channel;
58 	struct chan_info temp_list[MAX_6GHZ_CHANNEL];
59 	struct rnr_chan_weight *rnr_chan_info, temp;
60 	uint32_t weight;
61 	struct wlan_objmgr_psoc *psoc;
62 
63 	psoc = wlan_vdev_get_psoc(vdev);
64 	if (!psoc) {
65 		scm_err("Psoc is NULL");
66 		return;
67 	}
68 
69 	for (i = 0; i < chan_list->num_chan; i++)
70 		if (WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_list->chan[i].freq))
71 			temp_list[j++] = chan_list->chan[i];
72 
73 	tmp_list_count = j;
74 	scm_debug("Total 6ghz channels %d", tmp_list_count);
75 
76 	/* No Need to sort if the 6ghz channels are less than or one */
77 	if (tmp_list_count <= 1)
78 		return;
79 
80 	rnr_chan_info = qdf_mem_malloc(sizeof(*rnr_chan_info) * tmp_list_count);
81 	if (!rnr_chan_info)
82 		return;
83 
84 	/* compute the weightage */
85 	for (i = 0, j = 0; i < tmp_list_count; i++) {
86 		channel = scm_get_chan_meta(psoc, temp_list[i].freq);
87 		if (!channel)
88 			continue;
89 		weight = channel->bss_beacon_probe_count * BCN_PROBE_WEIGHTAGE +
90 			 channel->saved_profile_count * SAVED_PROFILE_WEIGHTAGE;
91 		rnr_chan_info[j].weight = weight;
92 		rnr_chan_info[j].chan_freq = temp_list[i].freq;
93 		rnr_chan_info[j].phymode = temp_list[i].phymode;
94 		rnr_chan_info[j].flags = temp_list[i].flags;
95 		j++;
96 		/*
97 		 * Log the info only if weight or bss_beacon_probe_count are
98 		 * non-zero to avoid excessive logging.
99 		 */
100 		if (weight || channel->bss_beacon_probe_count)
101 			scm_debug("Freq %d weight %d bcn_cnt %d",
102 				  temp_list[i].freq, weight,
103 				  channel->bss_beacon_probe_count);
104 	}
105 
106 	/* Sort the channel using selection sort - descending order */
107 	for (i = 0; i < tmp_list_count - 1; i++) {
108 		max = i;
109 		for (j = i + 1; j < tmp_list_count; j++) {
110 			if (rnr_chan_info[j].weight >
111 			    rnr_chan_info[max].weight)
112 				max = j;
113 		}
114 		if (max != i) {
115 			qdf_mem_copy(&temp, &rnr_chan_info[max],
116 				     sizeof(*rnr_chan_info));
117 			qdf_mem_copy(&rnr_chan_info[max], &rnr_chan_info[i],
118 				     sizeof(*rnr_chan_info));
119 			qdf_mem_copy(&rnr_chan_info[i], &temp,
120 				     sizeof(*rnr_chan_info));
121 		}
122 	}
123 
124 	/* update the 6g list based on the weightage */
125 	for (i = 0, j = 0; (i < NUM_CHANNELS && j < tmp_list_count); i++)
126 		if (wlan_reg_is_6ghz_chan_freq(chan_list->chan[i].freq)) {
127 			chan_list->chan[i].freq = rnr_chan_info[j].chan_freq;
128 			chan_list->chan[i].flags = rnr_chan_info[j].flags;
129 			chan_list->chan[i].phymode = rnr_chan_info[j++].phymode;
130 		}
131 
132 	qdf_mem_free(rnr_chan_info);
133 }
134 
135 static void scm_update_rnr_info(struct wlan_objmgr_psoc *psoc,
136 				struct scan_start_request *req)
137 {
138 	uint8_t i, num_bssid = 0, num_ssid = 0;
139 	uint8_t total_count = MAX_HINTS_PER_SCAN_REQ;
140 	uint32_t freq;
141 	struct meta_rnr_channel *chan;
142 	qdf_list_node_t *cur_node, *next_node = NULL;
143 	struct scan_rnr_node *rnr_node;
144 	struct chan_list *chan_list;
145 	QDF_STATUS status;
146 	bool hint = false;
147 
148 	if (!req)
149 		return;
150 
151 	chan_list = &req->scan_req.chan_list;
152 	for (i = 0; i < chan_list->num_chan; i++) {
153 		freq = chan_list->chan[i].freq;
154 
155 		chan = scm_get_chan_meta(psoc, freq);
156 		if (!chan || qdf_list_empty(&chan->rnr_list))
157 			continue;
158 
159 		qdf_list_peek_front(&chan->rnr_list, &cur_node);
160 		while (cur_node && total_count) {
161 			rnr_node = qdf_container_of(cur_node,
162 						    struct scan_rnr_node,
163 						    node);
164 			if (!qdf_is_macaddr_zero(&rnr_node->entry.bssid) &&
165 			    req->scan_req.num_hint_bssid <
166 			    WLAN_SCAN_MAX_HINT_BSSID) {
167 				qdf_mem_copy(&req->scan_req.hint_bssid[
168 							num_bssid].bssid,
169 					     &rnr_node->entry.bssid,
170 					     QDF_MAC_ADDR_SIZE);
171 				req->scan_req.hint_bssid[
172 					num_bssid++].freq_flags = freq << 16;
173 				req->scan_req.num_hint_bssid++;
174 				hint = true;
175 			}
176 			if (rnr_node->entry.short_ssid &&
177 			    req->scan_req.num_hint_s_ssid <
178 				   WLAN_SCAN_MAX_HINT_S_SSID) {
179 				req->scan_req.hint_s_ssid[
180 					num_ssid].short_ssid =
181 						rnr_node->entry.short_ssid;
182 				req->scan_req.hint_s_ssid[
183 					num_ssid++].freq_flags = freq << 16;
184 				req->scan_req.num_hint_s_ssid++;
185 				hint = true;
186 			}
187 
188 			if (hint) {
189 				total_count--;
190 				hint = false;
191 			}
192 			status = qdf_list_peek_next(&chan->rnr_list, cur_node,
193 						    &next_node);
194 			if (QDF_IS_STATUS_ERROR(status))
195 				break;
196 			cur_node = next_node;
197 			next_node = NULL;
198 		}
199 	}
200 }
201 
202 /**
203  * scm_add_rnr_info() - Add the cached RNR info to scan request
204  * @vdev: vdev on which scan request is issued
205  * @req: Scan start request
206  *
207  * Fetch the cached RNR info from scan db and update it to the scan request to
208  * include RNR channels in the scan request.
209  *
210  * Return: None
211  */
212 static void scm_add_rnr_info(struct wlan_objmgr_pdev *pdev,
213 			     struct scan_start_request *req)
214 {
215 	struct wlan_objmgr_psoc *psoc;
216 	struct channel_list_db *rnr_db;
217 
218 	psoc = wlan_pdev_get_psoc(pdev);
219 	if (!psoc)
220 		return;
221 	rnr_db = scm_get_rnr_channel_db(psoc);
222 	if (!rnr_db)
223 		return;
224 
225 	rnr_db->scan_count++;
226 	if (rnr_db->scan_count >= RNR_UPDATE_SCAN_CNT_THRESHOLD) {
227 		rnr_db->scan_count = 0;
228 		scm_rnr_db_flush(psoc);
229 		scm_update_rnr_from_scan_cache(pdev);
230 	}
231 
232 	scm_update_rnr_info(psoc, req);
233 }
234 #else
235 static void
236 scm_sort_6ghz_channel_list(struct wlan_objmgr_vdev *vdev,
237 			   struct chan_list *chan_list)
238 {
239 }
240 
241 static void scm_add_rnr_info(struct wlan_objmgr_pdev *pdev,
242 			     struct scan_start_request *req)
243 {
244 }
245 #endif
246 
247 static inline bool
248 scm_is_full_scan_by_userspace(struct chan_list *chan_list)
249 {
250 	return (chan_list->num_chan >= FULL_SCAN_CH_COUNT_MIN_BY_USERSPACE);
251 }
252 
253 static inline bool
254 scm_is_scan_type_exempted_from_optimization(struct scan_start_request *req)
255 {
256 	/* Dont modify the channel list for RRM type*/
257 	return (req->scan_req.scan_type == SCAN_TYPE_RRM);
258 }
259 
260 /**
261  * scm_add_all_valid_6g_channels() - Add all valid 6g channels to scan request
262  * @vdev: vdev on which scan request is issued
263  * @req: Scan start request
264  * @num_scan_ch: Total number of scan channels
265  * @is_colocated_6ghz_scan_enabled: colocated 6ghz scan flag enabled in scan req
266  *
267  * If colocated 6ghz scan flag present in host scan request or at least one 6G
268  * channel is present in the host scan request, then this API
269  * fills all remaining (other than channel(s) resent in host scan req) valid
270  * 6 GHz channel(s) to scan requests channel list and set the flag
271  * FLAG_SCAN_ONLY_IF_RNR_FOUND for each of those added channels.
272  * By this driver allows Firmware to scan 6G channels based on RNR IEs only.
273  *
274  * Return: None
275  */
276 void scm_add_all_valid_6g_channels(struct wlan_objmgr_pdev *pdev,
277 				   struct chan_list *chan_list,
278 				   uint8_t *num_scan_ch,
279 				   bool is_colocated_6ghz_scan_enabled)
280 {
281 	uint8_t i, j;
282 	enum channel_enum freq_idx;
283 	struct regulatory_channel *cur_chan_list;
284 	bool found;
285 	QDF_STATUS status;
286 	uint8_t temp_num_chan = 0;
287 
288 	if (!is_colocated_6ghz_scan_enabled) {
289 		scm_debug("flag is not set in scan req");
290 		return;
291 	}
292 
293 	cur_chan_list = qdf_mem_malloc(NUM_CHANNELS *
294 				sizeof(struct regulatory_channel));
295 	if (!cur_chan_list)
296 		return;
297 
298 	status = wlan_reg_get_current_chan_list(pdev, cur_chan_list);
299 	if (QDF_IS_STATUS_ERROR(status)) {
300 		qdf_mem_free(cur_chan_list);
301 		scm_debug("Failed to get cur_chan list");
302 		return;
303 	}
304 
305 	freq_idx =
306 		wlan_reg_get_chan_enum_for_freq(wlan_reg_min_6ghz_chan_freq());
307 	if (reg_is_chan_enum_invalid(freq_idx))
308 		return;
309 
310 	scm_debug("freq_idx:%d", freq_idx);
311 	temp_num_chan = chan_list->num_chan;
312 	for (i = freq_idx; i < NUM_CHANNELS; i++) {
313 		found = false;
314 		for (j = 0; j < temp_num_chan; j++) {
315 			if (cur_chan_list[i].center_freq ==
316 			    chan_list->chan[j].freq) {
317 				found = true;
318 				break;
319 			}
320 		}
321 		if (!found && cur_chan_list[i].state != CHANNEL_STATE_DISABLE &&
322 		    cur_chan_list[i].state != CHANNEL_STATE_INVALID) {
323 			chan_list->chan[chan_list->num_chan].freq =
324 						cur_chan_list[i].center_freq;
325 			chan_list->chan[chan_list->num_chan].flags =
326 						FLAG_SCAN_ONLY_IF_RNR_FOUND;
327 			chan_list->num_chan++;
328 		}
329 	}
330 
331 	scm_debug("prev num_chan:%d, current num_chan:%d", temp_num_chan,
332 		  chan_list->num_chan);
333 	*num_scan_ch = chan_list->num_chan;
334 	qdf_mem_free(cur_chan_list);
335 }
336 
337 static void
338 scm_copy_valid_channels(struct wlan_objmgr_psoc *psoc,
339 			enum scan_mode_6ghz scan_mode,
340 			struct scan_start_request *req,
341 			uint8_t *num_scan_ch)
342 {
343 	uint8_t i, num_ch = *num_scan_ch;
344 	struct chan_list *chan_list = &req->scan_req.chan_list;
345 	qdf_freq_t freq;
346 
347 	switch (scan_mode) {
348 	case SCAN_MODE_6G_NO_CHANNEL:
349 		/* Don't add any 6g channels */
350 		for (i = 0; i < chan_list->num_chan; i++)
351 			if (!wlan_reg_is_6ghz_chan_freq(
352 					chan_list->chan[i].freq))
353 				chan_list->chan[num_ch++] =
354 					chan_list->chan[i];
355 		break;
356 	case SCAN_MODE_6G_PSC_CHANNEL:
357 	case SCAN_MODE_6G_PSC_DUTY_CYCLE:
358 		/*
359 		 * Filter out non-PSC 6g channels if firmware doesn't
360 		 * supports RNR_ONLY scan flag/feature and the scan type is
361 		 * allowed to be optimized.
362 		 */
363 		if (!scm_is_6ghz_scan_optimization_supported(psoc) &&
364 		    !scm_is_scan_type_exempted_from_optimization(req)) {
365 			for (i = 0; i < chan_list->num_chan; i++) {
366 				freq = chan_list->chan[i].freq;
367 				if (!wlan_reg_is_6ghz_chan_freq(freq) ||
368 				    (wlan_reg_is_6ghz_chan_freq(freq) &&
369 				     wlan_reg_is_6ghz_psc_chan_freq(freq)))
370 					chan_list->chan[num_ch++] =
371 						chan_list->chan[i];
372 			}
373 			break;
374 		}
375 		/*
376 		 * Consider the complete channel list if firmware supports
377 		 * RNR_ONLY scan flag/feature.
378 		 */
379 		fallthrough;
380 	default:
381 		/*
382 		 * Allow all 2g/5g/6g channels. Below are also covered in this
383 		 * 1. SCAN_MODE_6G_ALL_CHANNEL: Copy all channels and RNR flag
384 		 *    won't be set for any channel.
385 		 * 2. SCAN_MODE_6G_PSC_CHANNEL: Copy all channels and RNR flag
386 		 *    will be set for non-PSC.
387 		 * 3. SCAN_MODE_6G_PSC_DUTY_CYCLE: Copy all channels and RNR
388 		 *    flag will be set for non-PSC for all scans and RNR flag
389 		 *    will be set for PSC channels only for duty cycle scan.
390 		 */
391 		num_ch = chan_list->num_chan;
392 	}
393 
394 	*num_scan_ch = num_ch;
395 }
396 
397 static inline void
398 scm_set_rnr_flag_non_psc_6g_ch(struct chan_info *chan, uint8_t num_chan)
399 {
400 	uint8_t i;
401 
402 	for (i = 0; i < num_chan; i++)
403 		if (wlan_reg_is_6ghz_chan_freq(chan[i].freq) &&
404 		    !wlan_reg_is_6ghz_psc_chan_freq(chan[i].freq))
405 			chan[i].flags = FLAG_SCAN_ONLY_IF_RNR_FOUND;
406 }
407 
408 static inline void
409 scm_set_rnr_flag_all_6g_ch(struct chan_info *chan, uint8_t num_chan)
410 {
411 	uint8_t i;
412 
413 	for (i = 0; i < num_chan; i++)
414 		if (wlan_reg_is_6ghz_chan_freq(chan[i].freq))
415 			chan[i].flags = FLAG_SCAN_ONLY_IF_RNR_FOUND;
416 }
417 
418 static bool scm_is_duty_cycle_scan(struct wlan_scan_obj *scan_obj)
419 {
420 	bool duty_cycle = false;
421 
422 	scan_obj->duty_cycle_cnt_6ghz++;
423 	if (scan_obj->duty_cycle_cnt_6ghz == 1)
424 		duty_cycle = true;
425 	if (scan_obj->scan_def.duty_cycle_6ghz == scan_obj->duty_cycle_cnt_6ghz)
426 		scan_obj->duty_cycle_cnt_6ghz = 0;
427 
428 	return duty_cycle;
429 }
430 
431 inline bool
432 scm_is_6ghz_scan_optimization_supported(struct wlan_objmgr_psoc *psoc)
433 {
434 	return wlan_psoc_nif_fw_ext_cap_get(psoc,
435 					    WLAN_SOC_CEXT_SCAN_PER_CH_CONFIG);
436 }
437 
438 void scm_add_channel_flags(struct wlan_objmgr_vdev *vdev,
439 			   struct chan_list *chan_list,
440 			   uint8_t *num_chan,
441 			   bool is_colocated_6ghz_scan_enabled,
442 			   bool is_pno_scan)
443 {
444 	struct wlan_scan_obj *scan_obj;
445 	enum scan_mode_6ghz scan_mode;
446 	struct wlan_objmgr_pdev *pdev;
447 	uint8_t num_scan_chan = *num_chan;
448 
449 	pdev = wlan_vdev_get_pdev(vdev);
450 	if (!pdev)
451 		return;
452 	scan_obj = wlan_vdev_get_scan_obj(vdev);
453 	if (!scan_obj) {
454 		scm_err("scan_obj is NULL");
455 		return;
456 	}
457 
458 	scan_mode = scan_obj->scan_def.scan_mode_6g;
459 
460 	switch (scan_mode) {
461 	case SCAN_MODE_6G_RNR_ONLY:
462 		/*
463 		 * When the ini is set to SCAN_MODE_6G_RNR_ONLY
464 		 * always set RNR flag for all(PSC and non-PSC) channels.
465 		 */
466 		scm_set_rnr_flag_all_6g_ch(&chan_list->chan[0], num_scan_chan);
467 		break;
468 	case SCAN_MODE_6G_PSC_CHANNEL:
469 		/*
470 		 * When the ini is set to SCAN_MODE_6G_PSC_CHANNEL,
471 		 * always set RNR flag for non-PSC channels.
472 		 */
473 		scm_set_rnr_flag_non_psc_6g_ch(&chan_list->chan[0],
474 					       num_scan_chan);
475 		break;
476 	case SCAN_MODE_6G_PSC_DUTY_CYCLE:
477 	case SCAN_MODE_6G_ALL_DUTY_CYCLE:
478 		if (!is_pno_scan && !scm_is_duty_cycle_scan(scan_obj))
479 			scm_set_rnr_flag_all_6g_ch(&chan_list->chan[0],
480 						   num_scan_chan);
481 		else if (scan_mode == SCAN_MODE_6G_PSC_DUTY_CYCLE) {
482 			if (is_pno_scan)
483 				scm_debug("Duty cycle scan not supported in pno");
484 			scm_set_rnr_flag_non_psc_6g_ch(&chan_list->chan[0],
485 						       num_scan_chan);
486 		}
487 		fallthrough;
488 		/* Even when the scan mode is SCAN_MODE_6G_PSC_DUTY_CYCLE or
489 		 * SCAN_MODE_6G_ALL_DUTY_CYCLE, it is better to add other 6 GHz
490 		 * channels to the channel list and set the bit
491 		 * FLAG_SCAN_ONLY_IF_RNR_FOUND for these new channels.
492 		 * This can help to find the APs which have co-located APs in
493 		 * given 2 GHz/5 GHz channels.
494 		 * Let it fallthrough as this is already addressed through the
495 		 * scan mode SCAN_MODE_6G_ALL_CHANNEL.
496 		 */
497 	case SCAN_MODE_6G_ALL_CHANNEL:
498 		/*
499 		 * When the ini is set to SCAN_MODE_6G_ALL_CHANNEL,
500 		 * Host fills all remaining (other than channel(s) present in
501 		 * host scan req) valid 6 GHz channel(s) to scan requests and
502 		 * set the flag FLAG_SCAN_ONLY_IF_RNR_FOUND for each remaining
503 		 * channels.
504 		 */
505 		scm_add_all_valid_6g_channels(pdev, chan_list, num_chan,
506 					      is_colocated_6ghz_scan_enabled);
507 		break;
508 	default:
509 		/*
510 		 * Don't set the RNR flag for SCAN_MODE_6G_NO_CHANNEL/
511 		 * SCAN_MODE_6G_RNR_ONLY
512 		 */
513 		break;
514 	}
515 }
516 
517 void
518 scm_update_6ghz_channel_list(struct scan_start_request *req,
519 			     struct wlan_scan_obj *scan_obj)
520 {
521 	struct wlan_objmgr_vdev *vdev = req->vdev;
522 	struct wlan_objmgr_pdev *pdev;
523 	struct chan_list *chan_list = &req->scan_req.chan_list;
524 	enum scan_mode_6ghz scan_mode;
525 	uint8_t num_scan_ch = 0;
526 	enum QDF_OPMODE op_mode;
527 	struct wlan_objmgr_psoc *psoc;
528 
529 	pdev = wlan_vdev_get_pdev(vdev);
530 	if (!pdev)
531 		return;
532 	psoc = wlan_pdev_get_psoc(pdev);
533 
534 	/* Dont update the channel list for not STA mode */
535 	op_mode = wlan_vdev_mlme_get_opmode(req->vdev);
536 	if (op_mode == QDF_SAP_MODE ||
537 	    op_mode == QDF_P2P_DEVICE_MODE ||
538 	    op_mode == QDF_P2P_CLIENT_MODE ||
539 	    op_mode == QDF_P2P_GO_MODE)
540 		return;
541 
542 	scan_mode = scan_obj->scan_def.scan_mode_6g;
543 	scm_debug("6g scan mode %d", scan_mode);
544 
545 	/*
546 	 * Host has learned RNR info/channels from previous scan. Add them to
547 	 * the scan request and don't set RNR_ONLY flag to scan them without
548 	 * optimization. Don't add RNR info if the scan type is exempted from
549 	 * optimization.
550 	 */
551 	if (scan_mode != SCAN_MODE_6G_NO_CHANNEL &&
552 	    scm_is_full_scan_by_userspace(chan_list) &&
553 	    !scm_is_scan_type_exempted_from_optimization(req))
554 		scm_add_rnr_info(pdev, req);
555 
556 	/* copy all the channels given by userspace */
557 	scm_copy_valid_channels(psoc, scan_mode, req, &num_scan_ch);
558 
559 	/* No more optimizations are needed in the below cases */
560 	if (!scm_is_full_scan_by_userspace(chan_list) ||
561 	    !scm_is_6ghz_scan_optimization_supported(psoc) ||
562 	    scm_is_scan_type_exempted_from_optimization(req))
563 		goto end;
564 
565 	scm_add_channel_flags(vdev, chan_list, &num_scan_ch,
566 			      req->scan_req.scan_policy_colocated_6ghz, false);
567 
568 end:
569 	chan_list->num_chan = num_scan_ch;
570 
571 	scm_sort_6ghz_channel_list(req->vdev, &req->scan_req.chan_list);
572 }
573 #endif
574