blob: cb8e89fb8bbff45d6025df780d99e801d2538e45 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/*===========================================================================
29
30 s a p C h S e l e c t . C
31 OVERVIEW:
32
33 This software unit holds the implementation of the WLAN SAP modules
34 functions for channel selection.
35
36 DEPENDENCIES:
37
38 Are listed for each API below.
39 ===========================================================================*/
40
41/*--------------------------------------------------------------------------
42 Include Files
43 ------------------------------------------------------------------------*/
44#include "cdf_trace.h"
45#include "csr_api.h"
46#include "sme_api.h"
47#include "sap_ch_select.h"
48#include "sap_internal.h"
49#ifdef ANI_OS_TYPE_QNX
50#include "stdio.h"
51#endif
52#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
53#include "lim_utils.h"
54#include "parser_api.h"
55#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
56
57#ifdef CONFIG_CNSS
58#include <net/cnss.h>
59#endif
60
61/*--------------------------------------------------------------------------
62 Function definitions
63 --------------------------------------------------------------------------*/
64
65/*--------------------------------------------------------------------------
66 Defines
67 --------------------------------------------------------------------------*/
68#define SAP_DEBUG
69
70#define IS_RSSI_VALID(extRssi, rssi) \
71 ( \
72 ((extRssi < rssi) ? true : false) \
73 )
74
75#define SET_ACS_BAND(acs_band, pSapCtx) \
76{ \
77 if (pSapCtx->acs_cfg->start_ch <= 14 && \
78 pSapCtx->acs_cfg->end_ch <= 14) \
79 acs_band = eCSR_DOT11_MODE_11g; \
80 else if (pSapCtx->acs_cfg->start_ch >= 14)\
81 acs_band = eCSR_DOT11_MODE_11a; \
82 else \
83 acs_band = eCSR_DOT11_MODE_abg; \
84}
85
86#ifdef FEATURE_WLAN_CH_AVOID
87sapSafeChannelType safe_channels[NUM_20MHZ_RF_CHANNELS] = {
88 /*CH , SAFE, default safe */
89 {1, true}
90 , /* RF_CHAN_1, */
91 {2, true}
92 , /* RF_CHAN_2, */
93 {3, true}
94 , /* RF_CHAN_3, */
95 {4, true}
96 , /* RF_CHAN_4, */
97 {5, true}
98 , /* RF_CHAN_5, */
99 {6, true}
100 , /* RF_CHAN_6, */
101 {7, true}
102 , /* RF_CHAN_7, */
103 {8, true}
104 , /* RF_CHAN_8, */
105 {9, true}
106 , /* RF_CHAN_9, */
107 {10, true}
108 , /* RF_CHAN_10, */
109 {11, true}
110 , /* RF_CHAN_11, */
111 {12, true}
112 , /* RF_CHAN_12, */
113 {13, true}
114 , /* RF_CHAN_13, */
115 {14, true}
116 , /* RF_CHAN_14, */
117 {240, true}
118 , /* RF_CHAN_240, */
119 {244, true}
120 , /* RF_CHAN_244, */
121 {248, true}
122 , /* RF_CHAN_248, */
123 {252, true}
124 , /* RF_CHAN_252, */
125 {208, true}
126 , /* RF_CHAN_208, */
127 {212, true}
128 , /* RF_CHAN_212, */
129 {216, true}
130 , /* RF_CHAN_216, */
131 {36, true}
132 , /* RF_CHAN_36, */
133 {40, true}
134 , /* RF_CHAN_40, */
135 {44, true}
136 , /* RF_CHAN_44, */
137 {48, true}
138 , /* RF_CHAN_48, */
139 {52, true}
140 , /* RF_CHAN_52, */
141 {56, true}
142 , /* RF_CHAN_56, */
143 {60, true}
144 , /* RF_CHAN_60, */
145 {64, true}
146 , /* RF_CHAN_64, */
147 {100, true}
148 , /* RF_CHAN_100, */
149 {104, true}
150 , /* RF_CHAN_104, */
151 {108, true}
152 , /* RF_CHAN_108, */
153 {112, true}
154 , /* RF_CHAN_112, */
155 {116, true}
156 , /* RF_CHAN_116, */
157 {120, true}
158 , /* RF_CHAN_120, */
159 {124, true}
160 , /* RF_CHAN_124, */
161 {128, true}
162 , /* RF_CHAN_128, */
163 {132, true}
164 , /* RF_CHAN_132, */
165 {136, true}
166 , /* RF_CHAN_136, */
167 {140, true}
168 , /* RF_CHAN_140, */
169 {144, true}
170 , /* RF_CHAN_144, */
171 {149, true}
172 , /* RF_CHAN_149, */
173 {153, true}
174 , /* RF_CHAN_153, */
175 {157, true}
176 , /* RF_CHAN_157, */
177 {161, true}
178 , /* RF_CHAN_161, */
179 {165, true}
180 , /* RF_CHAN_165, */
181};
182#endif
183
184typedef struct {
185 uint16_t chStartNum;
186 uint32_t weight;
187} sapAcsChannelInfo;
188
189sapAcsChannelInfo acs_ht40_channels5_g[] = {
190 {36, SAP_ACS_WEIGHT_MAX},
191 {44, SAP_ACS_WEIGHT_MAX},
192 {52, SAP_ACS_WEIGHT_MAX},
193 {60, SAP_ACS_WEIGHT_MAX},
194 {100, SAP_ACS_WEIGHT_MAX},
195 {108, SAP_ACS_WEIGHT_MAX},
196 {116, SAP_ACS_WEIGHT_MAX},
197 {124, SAP_ACS_WEIGHT_MAX},
198 {132, SAP_ACS_WEIGHT_MAX},
199 {140, SAP_ACS_WEIGHT_MAX},
200 {149, SAP_ACS_WEIGHT_MAX},
201 {157, SAP_ACS_WEIGHT_MAX},
202};
203
204sapAcsChannelInfo acs_ht80_channels[] = {
205 {36, SAP_ACS_WEIGHT_MAX},
206 {52, SAP_ACS_WEIGHT_MAX},
207 {100, SAP_ACS_WEIGHT_MAX},
208 {116, SAP_ACS_WEIGHT_MAX},
209 {132, SAP_ACS_WEIGHT_MAX},
210 {149, SAP_ACS_WEIGHT_MAX},
211};
212
213sapAcsChannelInfo acs_ht40_channels24_g[] = {
214 {1, SAP_ACS_WEIGHT_MAX},
215 {2, SAP_ACS_WEIGHT_MAX},
216 {3, SAP_ACS_WEIGHT_MAX},
217 {4, SAP_ACS_WEIGHT_MAX},
218 {9, SAP_ACS_WEIGHT_MAX},
219};
220
221#define CHANNEL_165 165
222
223/* rssi discount for channels in PCL */
224#define PCL_RSSI_DISCOUNT 10
225
226#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
227/**
228 * sap_check_n_add_channel() - checks and add given channel in sap context's
229 * avoid_channels_info struct
230 * @sap_ctx: sap context.
231 * @new_channel: channel to be added to sap_ctx's avoid ch info
232 *
233 * sap_ctx contains sap_avoid_ch_info strcut containing the list of channels on
234 * which MDM device's AP with MCC was detected. This function will add channels
235 * to that list after checking for duplicates.
236 *
237 * Return: true: if channel was added or already present
238 * else false: if channel list was already full.
239 */
240bool
241sap_check_n_add_channel(ptSapContext sap_ctx,
242 uint8_t new_channel)
243{
244 uint8_t i = 0;
245 struct sap_avoid_channels_info *ie_info =
246 &sap_ctx->sap_detected_avoid_ch_ie;
247
248 for (i = 0; i < sizeof(ie_info->channels); i++) {
249 if (ie_info->channels[i] == new_channel)
250 break;
251
252 if (ie_info->channels[i] == 0) {
253 ie_info->channels[i] = new_channel;
254 break;
255 }
256 }
257 if (i == sizeof(ie_info->channels))
258 return false;
259 else
260 return true;
261}
262/**
263 * sap_check_n_add_overlapped_chnls() - checks & add overlapped channels
264 * to primary channel in 2.4Ghz band.
265 * @sap_ctx: sap context.
266 * @primary_chnl: primary channel to be avoided.
267 *
268 * sap_ctx contains sap_avoid_ch_info struct containing the list of channels on
269 * which MDM device's AP with MCC was detected. This function will add channels
270 * to that list after checking for duplicates.
271 *
272 * Return: true: if channel was added or already present
273 * else false: if channel list was already full.
274 */
275static bool
276sap_check_n_add_overlapped_chnls(ptSapContext sap_ctx, uint8_t primary_channel)
277{
278 uint8_t i = 0, j = 0, upper_chnl = 0, lower_chnl = 0;
279 struct sap_avoid_channels_info *ie_info =
280 &sap_ctx->sap_detected_avoid_ch_ie;
281 /*
282 * if primary channel less than channel 1 or out of 2g band then
283 * no further process is required. return true in this case.
284 */
285 if (primary_channel < CHANNEL_1 || primary_channel > CHANNEL_14)
286 return true;
287
288 /* lower channel is one channel right before primary channel */
289 lower_chnl = primary_channel - 1;
290 /* upper channel is one channel right after primary channel */
291 upper_chnl = primary_channel + 1;
292
293 /* lower channel needs to be non-zero, zero is not valid channel */
294 if (lower_chnl > (CHANNEL_1 - 1)) {
295 for (i = 0; i < sizeof(ie_info->channels); i++) {
296 if (ie_info->channels[i] == lower_chnl)
297 break;
298 if (ie_info->channels[i] == 0) {
299 ie_info->channels[i] = lower_chnl;
300 break;
301 }
302 }
303 }
304 /* upper channel needs to be atleast last channel in 2.4Ghz band */
305 if (upper_chnl < (CHANNEL_14 + 1)) {
306 for (j = 0; j < sizeof(ie_info->channels); j++) {
307 if (ie_info->channels[j] == upper_chnl)
308 break;
309 if (ie_info->channels[j] == 0) {
310 ie_info->channels[j] = upper_chnl;
311 break;
312 }
313 }
314 }
315 if (i == sizeof(ie_info->channels) || j == sizeof(ie_info->channels))
316 return false;
317 else
318 return true;
319}
320
321/**
322 * sap_process_avoid_ie() - processes the detected Q2Q IE
323 * context's avoid_channels_info struct
324 * @hal: hal handle
325 * @sap_ctx: sap context.
326 * @scan_result: scan results for ACS scan.
327 * @spect_info: spectrum weights array to update
328 *
329 * Detection of Q2Q IE indicates presence of another MDM device with its AP
330 * operating in MCC mode. This function parses the scan results and processes
331 * the Q2Q IE if found. It then extracts the channels and populates them in
332 * sap_ctx struct. It also increases the weights of those channels so that
333 * ACS logic will avoid those channels in its selection algorithm.
334 *
335 * Return: void
336 */
337void sap_process_avoid_ie(tHalHandle hal,
338 ptSapContext sap_ctx,
339 tScanResultHandle scan_result,
340 tSapChSelSpectInfo *spect_info)
341{
342 uint32_t total_ie_len = 0;
343 uint8_t *temp_ptr = NULL;
344 uint8_t i = 0;
345 struct sAvoidChannelIE *avoid_ch_ie;
346 tCsrScanResultInfo *node = NULL;
347 tpAniSirGlobal mac_ctx = NULL;
348 tSapSpectChInfo *spect_ch = NULL;
349
350 mac_ctx = PMAC_STRUCT(hal);
351 spect_ch = spect_info->pSpectCh;
352 node = sme_scan_result_get_first(hal, scan_result);
353
354 while (node) {
355 total_ie_len = (node->BssDescriptor.length +
356 sizeof(uint16_t) + sizeof(uint32_t) -
357 sizeof(tSirBssDescription));
358 temp_ptr = cfg_get_vendor_ie_ptr_from_oui(mac_ctx,
359 SIR_MAC_QCOM_VENDOR_OUI,
360 SIR_MAC_QCOM_VENDOR_SIZE,
361 ((uint8_t *)&node->BssDescriptor.ieFields),
362 total_ie_len);
363
364 if (temp_ptr) {
365 avoid_ch_ie = (struct sAvoidChannelIE *)temp_ptr;
366 if (avoid_ch_ie->type != QCOM_VENDOR_IE_MCC_AVOID_CH)
367 continue;
368
369 sap_ctx->sap_detected_avoid_ch_ie.present = 1;
370 CDF_TRACE(CDF_MODULE_ID_SAP,
371 CDF_TRACE_LEVEL_DEBUG,
372 "Q2Q IE - avoid ch %d",
373 avoid_ch_ie->channel);
374 /* add this channel to to_avoid channel list */
375 sap_check_n_add_channel(sap_ctx,
376 avoid_ch_ie->channel);
377 sap_check_n_add_overlapped_chnls(sap_ctx,
378 avoid_ch_ie->channel);
379 /*
380 * Mark weight of these channel present in IE to MAX
381 * so that ACS logic will to avoid thse channels
382 */
383 for (i = 0; i < spect_info->numSpectChans; i++)
384 if (spect_ch[i].chNum == avoid_ch_ie->channel) {
385 /*
386 * weight is set more than max so that,
387 * in the case of other channels being
388 * assigned max weight due to noise,
389 * they may be preferred over channels
390 * with Q2Q IE.
391 */
392 spect_ch[i].weight = SAP_ACS_WEIGHT_MAX + 1;
393 spect_ch[i].weight_copy =
394 SAP_ACS_WEIGHT_MAX + 1;
395 break;
396 }
397 } /* if (temp_ptr) */
398 node = sme_scan_result_get_next(hal, scan_result);
399 }
400}
401#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
402
403#ifdef FEATURE_WLAN_CH_AVOID
404/*==========================================================================
405 FUNCTION sap_update_unsafe_channel_list
406
407 DESCRIPTION
408 Function Undate unsafe channel list table
409
410 DEPENDENCIES
411 NA.
412
413 IN
414 SapContext pointer
415
416 RETURN VALUE
417 NULL
418 ============================================================================*/
419#ifdef CONFIG_CNSS
420void sap_update_unsafe_channel_list(ptSapContext pSapCtx)
421{
422 uint16_t i, j;
423 uint16_t unsafe_channel_list[NUM_20MHZ_RF_CHANNELS];
424 uint16_t unsafe_channel_count = 0;
425
426 /* Flush, default set all channel safe */
427 for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) {
428 safe_channels[i].isSafe = true;
429 }
430
431 /* Try to find unsafe channel */
432#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) || \
433 defined(WLAN_FEATURE_MBSSID)
434 for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) {
435 if (pSapCtx->dfs_ch_disable == true) {
436 if (CDS_IS_DFS_CH(safe_channels[i].channelNumber)) {
437 safe_channels[i].isSafe = false;
438 CDF_TRACE(CDF_MODULE_ID_SAP,
439 CDF_TRACE_LEVEL_INFO_HIGH,
440 "%s: DFS Ch %d is not safe in"
441 " Concurrent mode",
442 __func__,
443 safe_channels[i].channelNumber);
444 }
445 }
446 }
447#endif
448
449 cnss_get_wlan_unsafe_channel(unsafe_channel_list,
450 &unsafe_channel_count,
451 sizeof(unsafe_channel_list));
452
453 for (i = 0; i < unsafe_channel_count; i++) {
454 for (j = 0; j < NUM_20MHZ_RF_CHANNELS; j++) {
455 if (safe_channels[j].channelNumber ==
456 unsafe_channel_list[i]) {
457 /* Found unsafe channel, update it */
458 safe_channels[j].isSafe = false;
459 CDF_TRACE(CDF_MODULE_ID_SAP,
460 CDF_TRACE_LEVEL_ERROR,
461 FL("CH %d is not safe"),
462 unsafe_channel_list[i]);
463 break;
464 }
465 }
466 }
467
468 return;
469}
470#else
471void sap_update_unsafe_channel_list(ptSapContext pSapCtx)
472{
473 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
474 "%s: Not implemented", __func__);
475 return;
476}
477#endif
478
479#endif /* FEATURE_WLAN_CH_AVOID */
480
481/*==========================================================================
482 FUNCTION sap_cleanup_channel_list
483
484 DESCRIPTION
485 Function sap_cleanup_channel_list frees up the memory allocated to the channel list.
486
487 DEPENDENCIES
488 NA.
489
490 PARAMETERS
491
492 IN
493 NULL
494
495 RETURN VALUE
496 NULL
497 ============================================================================*/
498
499void sap_cleanup_channel_list(
500#ifdef WLAN_FEATURE_MBSSID
501 void *p_cds_gctx
502#else
503 void
504#endif
505 ) {
506#ifndef WLAN_FEATURE_MBSSID
507 void *p_cds_gctx = cds_get_global_context();
508#endif
509 ptSapContext pSapCtx;
510
511 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
512 "Cleaning up the channel list structure");
513
514 if (NULL == p_cds_gctx) {
515 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL,
516 "SAP Global Context is NULL");
517 return;
518 }
519
520 pSapCtx = CDS_GET_SAP_CB(p_cds_gctx);
521 if (NULL == pSapCtx) {
522 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_FATAL,
523 "SAP Context is NULL");
524 return;
525 }
526
527 pSapCtx->SapChnlList.numChannel = 0;
528 if (pSapCtx->SapChnlList.channelList) {
529 cdf_mem_free(pSapCtx->SapChnlList.channelList);
530 pSapCtx->SapChnlList.channelList = NULL;
531 }
532
533 pSapCtx->SapAllChnlList.numChannel = 0;
534 if (pSapCtx->SapAllChnlList.channelList) {
535 cdf_mem_free(pSapCtx->SapAllChnlList.channelList);
536 pSapCtx->SapAllChnlList.channelList = NULL;
537 }
538}
539
540/**
541 * sap_select_preferred_channel_from_channel_list() - to calc best cahnnel
542 * @best_chnl: best channel already calculated among all the chanels
543 * @sap_ctx: sap context
544 * @spectinfo_param: Pointer to tSapChSelSpectInfo structure
545 *
546 * This function calculates the best channel among the configured channel list.
547 * If channel list not configured then returns the best channel calculated
548 * among all the channel list.
549 *
550 * Return: uint8_t best channel
551 */
552uint8_t sap_select_preferred_channel_from_channel_list(uint8_t best_chnl,
553 ptSapContext sap_ctx,
554 tSapChSelSpectInfo *spectinfo_param)
555{
556 uint8_t i = 0;
557
558 /*
559 * If Channel List is not Configured don't do anything
560 * Else return the Best Channel from the Channel List
561 */
562 if ((NULL == sap_ctx->acs_cfg->ch_list) ||
563 (NULL == spectinfo_param) ||
564 (0 == sap_ctx->acs_cfg->ch_list_count))
565 return best_chnl;
566
567 if (best_chnl <= 0 || best_chnl > 252)
568 return SAP_CHANNEL_NOT_SELECTED;
569
570 /* Select the best channel from allowed list */
571 for (i = 0; i < sap_ctx->acs_cfg->ch_list_count; i++) {
572 if (sap_ctx->acs_cfg->ch_list[i] == best_chnl) {
573 CDF_TRACE(CDF_MODULE_ID_SAP,
574 CDF_TRACE_LEVEL_INFO_HIGH,
575 "Best channel is: %d",
576 best_chnl);
577 return best_chnl;
578 }
579 }
580
581 return SAP_CHANNEL_NOT_SELECTED;
582}
583
584/*==========================================================================
585 FUNCTION sap_chan_sel_init
586
587 DESCRIPTION
588 Function sap_chan_sel_init allocates the memory, intializes the
589 structures used by the channel selection algorithm
590
591 DEPENDENCIES
592 NA.
593
594 PARAMETERS
595
596 IN
597 halHandle : Pointer to tHalHandle
598 *pSpectInfoParams : Pointer to tSapChSelSpectInfo structure
599 pSapCtx : Pointer to SAP Context
600
601 RETURN VALUE
602 bool: Success or FAIL
603
604 SIDE EFFECTS
605 ============================================================================*/
606bool sap_chan_sel_init(tHalHandle halHandle,
607 tSapChSelSpectInfo *pSpectInfoParams, ptSapContext pSapCtx)
608{
609 tSapSpectChInfo *pSpectCh = NULL;
610 uint8_t *pChans = NULL;
611 uint16_t channelnum = 0;
612 tpAniSirGlobal pMac = PMAC_STRUCT(halHandle);
613 bool chSafe = true;
614#ifdef FEATURE_WLAN_CH_AVOID
615 uint16_t i;
616#endif
617 uint32_t dfs_master_cap_enabled;
618 bool include_dfs_ch = true;
619
620 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH, "In %s",
621 __func__);
622
623 pSpectInfoParams->numSpectChans =
624 pMac->scan.base_channels.numChannels;
625
626 /* Allocate memory for weight computation of 2.4GHz */
627 pSpectCh =
628 (tSapSpectChInfo *) cdf_mem_malloc((pSpectInfoParams->numSpectChans)
629 * sizeof(*pSpectCh));
630
631 if (pSpectCh == NULL) {
632 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
633 "In %s, CDF_MALLOC_ERR", __func__);
634 return eSAP_FALSE;
635 }
636
637 cdf_mem_zero(pSpectCh,
638 (pSpectInfoParams->numSpectChans) * sizeof(*pSpectCh));
639
640 /* Initialize the pointers in the DfsParams to the allocated memory */
641 pSpectInfoParams->pSpectCh = pSpectCh;
642
643 pChans = pMac->scan.base_channels.channelList;
644
645#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE) || defined(WLAN_FEATURE_MBSSID)
646 if (pSapCtx->dfs_ch_disable == true)
647 include_dfs_ch = false;
648#endif
649 sme_cfg_get_int(halHandle, WNI_CFG_DFS_MASTER_ENABLED,
650 &dfs_master_cap_enabled);
651 if (dfs_master_cap_enabled == 0)
652 include_dfs_ch = false;
653
654 /* Fill the channel number in the spectrum in the operating freq band */
655 for (channelnum = 0;
656 channelnum < pSpectInfoParams->numSpectChans;
657 channelnum++, pChans++) {
658 chSafe = true;
659
660 /* check if the channel is in NOL blacklist */
661 if (sap_dfs_is_channel_in_nol_list(pSapCtx, *pChans,
662 PHY_SINGLE_CHANNEL_CENTERED)) {
663 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
664 "In %s, Ch %d is in NOL list", __func__,
665 *pChans);
666 chSafe = false;
667 continue;
668 }
669
670 if (include_dfs_ch == false) {
671 if (CDS_IS_DFS_CH(*pChans)) {
672 chSafe = false;
673 CDF_TRACE(CDF_MODULE_ID_SAP,
674 CDF_TRACE_LEVEL_INFO_HIGH,
675 "In %s, DFS Ch %d not considered for ACS",
676 __func__, *pChans);
677 continue;
678 }
679 }
680
681#ifdef FEATURE_WLAN_CH_AVOID
682 for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) {
683 if ((safe_channels[i].channelNumber == *pChans) &&
684 (false == safe_channels[i].isSafe)) {
685 CDF_TRACE(CDF_MODULE_ID_SAP,
686 CDF_TRACE_LEVEL_INFO_HIGH,
687 "In %s, Ch %d is not safe", __func__,
688 *pChans);
689 chSafe = false;
690 break;
691 }
692 }
693#endif /* FEATURE_WLAN_CH_AVOID */
694
695 /* OFDM rates are not supported on channel 14 */
696 if (*pChans == 14 &&
697 eCSR_DOT11_MODE_11b != pSapCtx->csr_roamProfile.phyMode) {
698 pSpectCh++;
699 continue;
700 }
701
702 if (true == chSafe) {
703 pSpectCh->chNum = *pChans;
704 pSpectCh->valid = eSAP_TRUE;
705 pSpectCh->rssiAgr = SOFTAP_MIN_RSSI; /* Initialise for all channels */
706 pSpectCh->channelWidth = SOFTAP_HT20_CHANNELWIDTH; /* Initialise 20MHz for all the Channels */
707 }
708 pSpectCh++;
709 }
710 return eSAP_TRUE;
711}
712
713/*==========================================================================
714 FUNCTION sapweight_rssi_count
715
716 DESCRIPTION
717 Function weightRssiCount calculates the channel weight due to rssi
718 and data count(here number of BSS observed)
719
720 DEPENDENCIES
721 NA.
722
723 PARAMETERS
724
725 IN
726 rssi : Max signal strength receieved from a BSS for the channel
727 count : Number of BSS observed in the channel
728
729 RETURN VALUE
730 uint32_t : Calculated channel weight based on above two
731
732 SIDE EFFECTS
733 ============================================================================*/
734uint32_t sapweight_rssi_count(int8_t rssi, uint16_t count)
735{
736 int32_t rssiWeight = 0;
737 int32_t countWeight = 0;
738 uint32_t rssicountWeight = 0;
739
740 /* Weight from RSSI */
741 rssiWeight = SOFTAP_RSSI_WEIGHT * (rssi - SOFTAP_MIN_RSSI)
742 / (SOFTAP_MAX_RSSI - SOFTAP_MIN_RSSI);
743
744 if (rssiWeight > SOFTAP_RSSI_WEIGHT)
745 rssiWeight = SOFTAP_RSSI_WEIGHT;
746 else if (rssiWeight < 0)
747 rssiWeight = 0;
748
749 /* Weight from data count */
750 countWeight = SOFTAP_COUNT_WEIGHT * (count - SOFTAP_MIN_COUNT)
751 / (SOFTAP_MAX_COUNT - SOFTAP_MIN_COUNT);
752
753 if (countWeight > SOFTAP_COUNT_WEIGHT)
754 countWeight = SOFTAP_COUNT_WEIGHT;
755
756 rssicountWeight = rssiWeight + countWeight;
757
758 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
759 "In %s, rssiWeight=%d, countWeight=%d, rssicountWeight=%d",
760 __func__, rssiWeight, countWeight, rssicountWeight);
761
762 return rssicountWeight;
763}
764
765/**
766 * sap_update_rssi_bsscount() - updates bss count and rssi effect.
767 *
768 * @pSpectCh: Channel Information
769 * @offset: Channel Offset
770 * @sap_24g: Channel is in 2.4G or 5G
771 *
772 * sap_update_rssi_bsscount updates bss count and rssi effect based
773 * on the channel offset.
774 *
775 * Return: None.
776 */
777
778void sap_update_rssi_bsscount(tSapSpectChInfo *pSpectCh, int32_t offset,
779 bool sap_24g)
780{
781 tSapSpectChInfo *pExtSpectCh = NULL;
782 int32_t rssi, rsssi_effect;
783
784 pExtSpectCh = (pSpectCh + offset);
785 if (pExtSpectCh != NULL) {
786 ++pExtSpectCh->bssCount;
787 switch (offset) {
788 case -1:
789 case 1:
790 rsssi_effect = sap_24g ?
791 SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY :
792 SAP_SUBBAND1_RSSI_EFFECT_PRIMARY;
793 break;
794 case -2:
795 case 2:
796 rsssi_effect = sap_24g ?
797 SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY :
798 SAP_SUBBAND2_RSSI_EFFECT_PRIMARY;
799 break;
800 case -3:
801 case 3:
802 rsssi_effect = sap_24g ?
803 SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY :
804 SAP_SUBBAND3_RSSI_EFFECT_PRIMARY;
805 break;
806 case -4:
807 case 4:
808 rsssi_effect =
809 SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY;
810 break;
811 default:
812 rsssi_effect = 0;
813 break;
814 }
815
816 rssi = pSpectCh->rssiAgr + rsssi_effect;
817 if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi))
818 pExtSpectCh->rssiAgr = rssi;
819 if (pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI)
820 pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI;
821 }
822}
823
824/**
825 * sap_upd_chan_spec_params() - sap_upd_chan_spec_params
826 * updates channel parameters obtained from Beacon
827 * @pBeaconStruct Beacon strucutre populated by parse_beacon function
828 * @channelWidth Channel width
829 * @secondaryChannelOffset Secondary Channel Offset
830 * @vhtSupport If channel supports VHT
831 * @centerFreq Central frequency for the given channel.
832 *
833 * sap_upd_chan_spec_params updates the spectrum channels based on the
834 * pBeaconStruct obtained from Beacon IE
835 *
836 * Return: NA.
837 */
838
839void sap_upd_chan_spec_params(tSirProbeRespBeacon *pBeaconStruct,
840 uint16_t *channelWidth,
841 uint16_t *secondaryChannelOffset,
842 uint16_t *vhtSupport,
843 uint16_t *centerFreq)
844{
845 if (NULL == pBeaconStruct) {
846 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
847 FL("pBeaconStruct is NULL"));
848 return;
849 }
850
851 if (pBeaconStruct->HTCaps.present && pBeaconStruct->HTInfo.present) {
852 *channelWidth = pBeaconStruct->HTCaps.supportedChannelWidthSet;
853 *secondaryChannelOffset = pBeaconStruct->HTInfo.
854 secondaryChannelOffset;
855
856 if (pBeaconStruct->VHTOperation.present) {
857 *vhtSupport = pBeaconStruct->VHTOperation.present;
858 if (pBeaconStruct->VHTOperation.chanWidth >
859 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) {
860 *channelWidth = eHT_CHANNEL_WIDTH_80MHZ;
861 *centerFreq = pBeaconStruct->VHTOperation.
862 chanCenterFreqSeg1;
863 }
864 }
865 }
866}
867
868/**
869 * sap_interference_rssi_count_5G() - sap_interference_rssi_count
870 * considers the Adjacent channel rssi and
871 * data count(here number of BSS observed)
872 * @spect_ch: Channel Information
873 * @chan_width: Channel width parsed from beacon IE
874 * @sec_chan_offset: Secondary Channel Offset
875 * @center_freq: Central frequency for the given channel.
876 * @channel_id: channel_id
877 *
878 * sap_interference_rssi_count_5G considers the Adjacent channel rssi
879 * and data count(here number of BSS observed)
880 *
881 * Return: NA.
882 */
883
884void sap_interference_rssi_count_5G(tSapSpectChInfo *spect_ch,
885 uint16_t chan_width,
886 uint16_t sec_chan_offset,
887 uint16_t center_freq, uint8_t channel_id)
888{
889 if (NULL == spect_ch) {
890 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
891 FL("spect_ch is NULL"));
892 return;
893 }
894
895 /* Updating the received ChannelWidth */
896 if (spect_ch->channelWidth != chan_width)
897 spect_ch->channelWidth = chan_width;
898 /* If received ChannelWidth is other than HT20,
899 * we need to update the extension channel Params as well
900 * chan_width == 0, HT20
901 * chan_width == 1, HT40
902 * chan_width == 2, VHT80
903 */
904
905 switch (spect_ch->channelWidth) {
906 case eHT_CHANNEL_WIDTH_40MHZ: /* HT40 */
907 switch (sec_chan_offset) {
908 /* Above the Primary Channel */
909 case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
910 sap_update_rssi_bsscount(spect_ch, 1, false);
911 break;
912
913 /* Below the Primary channel */
914 case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
915 sap_update_rssi_bsscount(spect_ch, -1, false);
916 break;
917 }
918 break;
919 case eHT_CHANNEL_WIDTH_80MHZ: /* VHT80 */
920 if ((center_freq - channel_id) == 6) {
921 sap_update_rssi_bsscount(spect_ch, 1, false);
922 sap_update_rssi_bsscount(spect_ch, 2, false);
923 sap_update_rssi_bsscount(spect_ch, 3, false);
924 } else if ((center_freq - channel_id) == 2) {
925 sap_update_rssi_bsscount(spect_ch, -1, false);
926 sap_update_rssi_bsscount(spect_ch, 1, false);
927 sap_update_rssi_bsscount(spect_ch, 2, false);
928 } else if ((center_freq - channel_id) == -2) {
929 sap_update_rssi_bsscount(spect_ch, -2, false);
930 sap_update_rssi_bsscount(spect_ch, -1, false);
931 sap_update_rssi_bsscount(spect_ch, 1, false);
932 } else if ((center_freq - channel_id) == -6) {
933 sap_update_rssi_bsscount(spect_ch, -1, false);
934 sap_update_rssi_bsscount(spect_ch, -2, false);
935 sap_update_rssi_bsscount(spect_ch, -3, false);
936 }
937 break;
938 default:
939 break;
940 }
941}
942
943/**
944 * sap_interference_rssi_count() - sap_interference_rssi_count
945 * considers the Adjacent channel rssi
946 * and data count(here number of BSS observed)
947 * @spect_ch Channel Information
948 *
949 * sap_interference_rssi_count considers the Adjacent channel rssi
950 * and data count(here number of BSS observed)
951 *
952 * Return: None.
953 */
954
955void sap_interference_rssi_count(tSapSpectChInfo *spect_ch)
956{
957 if (NULL == spect_ch) {
958 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
959 "%s: spect_ch is NULL", __func__);
960 return;
961 }
962
963 switch (spect_ch->chNum) {
964 case CHANNEL_1:
965 sap_update_rssi_bsscount(spect_ch, 1, true);
966 sap_update_rssi_bsscount(spect_ch, 2, true);
967 sap_update_rssi_bsscount(spect_ch, 3, true);
968 sap_update_rssi_bsscount(spect_ch, 4, true);
969 break;
970
971 case CHANNEL_2:
972 sap_update_rssi_bsscount(spect_ch, -1, true);
973 sap_update_rssi_bsscount(spect_ch, 1, true);
974 sap_update_rssi_bsscount(spect_ch, 2, true);
975 sap_update_rssi_bsscount(spect_ch, 3, true);
976 sap_update_rssi_bsscount(spect_ch, 4, true);
977 break;
978 case CHANNEL_3:
979 sap_update_rssi_bsscount(spect_ch, -2, true);
980 sap_update_rssi_bsscount(spect_ch, -1, true);
981 sap_update_rssi_bsscount(spect_ch, 1, true);
982 sap_update_rssi_bsscount(spect_ch, 2, true);
983 sap_update_rssi_bsscount(spect_ch, 3, true);
984 sap_update_rssi_bsscount(spect_ch, 4, true);
985 break;
986 case CHANNEL_4:
987 sap_update_rssi_bsscount(spect_ch, -3, true);
988 sap_update_rssi_bsscount(spect_ch, -2, true);
989 sap_update_rssi_bsscount(spect_ch, -1, true);
990 sap_update_rssi_bsscount(spect_ch, 1, true);
991 sap_update_rssi_bsscount(spect_ch, 2, true);
992 sap_update_rssi_bsscount(spect_ch, 3, true);
993 sap_update_rssi_bsscount(spect_ch, 4, true);
994 break;
995
996 case CHANNEL_5:
997 case CHANNEL_6:
998 case CHANNEL_7:
999 case CHANNEL_8:
1000 case CHANNEL_9:
1001 case CHANNEL_10:
1002 sap_update_rssi_bsscount(spect_ch, -4, true);
1003 sap_update_rssi_bsscount(spect_ch, -3, true);
1004 sap_update_rssi_bsscount(spect_ch, -2, true);
1005 sap_update_rssi_bsscount(spect_ch, -1, true);
1006 sap_update_rssi_bsscount(spect_ch, 1, true);
1007 sap_update_rssi_bsscount(spect_ch, 2, true);
1008 sap_update_rssi_bsscount(spect_ch, 3, true);
1009 sap_update_rssi_bsscount(spect_ch, 4, true);
1010 break;
1011
1012 case CHANNEL_11:
1013 sap_update_rssi_bsscount(spect_ch, -4, true);
1014 sap_update_rssi_bsscount(spect_ch, -3, true);
1015 sap_update_rssi_bsscount(spect_ch, -2, true);
1016 sap_update_rssi_bsscount(spect_ch, -1, true);
1017 sap_update_rssi_bsscount(spect_ch, 1, true);
1018 sap_update_rssi_bsscount(spect_ch, 2, true);
1019 sap_update_rssi_bsscount(spect_ch, 3, true);
1020 break;
1021
1022 case CHANNEL_12:
1023 sap_update_rssi_bsscount(spect_ch, -4, true);
1024 sap_update_rssi_bsscount(spect_ch, -3, true);
1025 sap_update_rssi_bsscount(spect_ch, -2, true);
1026 sap_update_rssi_bsscount(spect_ch, -1, true);
1027 sap_update_rssi_bsscount(spect_ch, 1, true);
1028 sap_update_rssi_bsscount(spect_ch, 2, true);
1029 break;
1030
1031 case CHANNEL_13:
1032 sap_update_rssi_bsscount(spect_ch, -4, true);
1033 sap_update_rssi_bsscount(spect_ch, -3, true);
1034 sap_update_rssi_bsscount(spect_ch, -2, true);
1035 sap_update_rssi_bsscount(spect_ch, -1, true);
1036 sap_update_rssi_bsscount(spect_ch, 1, true);
1037 break;
1038
1039 case CHANNEL_14:
1040 sap_update_rssi_bsscount(spect_ch, -4, true);
1041 sap_update_rssi_bsscount(spect_ch, -3, true);
1042 sap_update_rssi_bsscount(spect_ch, -2, true);
1043 sap_update_rssi_bsscount(spect_ch, -1, true);
1044 break;
1045
1046 default:
1047 break;
1048 }
1049}
1050
1051/*==========================================================================
1052 Function ch_in_pcl
1053
1054 Description
1055 Check if a channel is in the preferred channel list
1056
1057 Parameters
1058 sap_ctx SAP context pointer
1059 channel input channel number
1060
1061 Return Value
1062 true: channel is in PCL
1063 false: channel is not in PCL
1064 ==========================================================================*/
1065bool ch_in_pcl(ptSapContext sap_ctx, uint8_t channel)
1066{
1067 uint32_t i;
1068
1069 for (i = 0; i < sap_ctx->acs_cfg->pcl_ch_count; i++) {
1070 if (channel == sap_ctx->acs_cfg->pcl_channels[i])
1071 return true;
1072 }
1073
1074 return false;
1075}
1076
1077/*==========================================================================
1078 FUNCTION sap_compute_spect_weight
1079
1080 DESCRIPTION
1081 Main function for computing the weight of each channel in the
1082 spectrum based on the RSSI value of the BSSes on the channel
1083 and number of BSS
1084
1085 DEPENDENCIES
1086 NA.
1087
1088 PARAMETERS
1089
1090 IN
1091 pSpectInfoParams : Pointer to the tSpectInfoParams structure
1092 halHandle : Pointer to HAL handle
1093 pResult : Pointer to tScanResultHandle
1094
1095 RETURN VALUE
1096 void : NULL
1097
1098 SIDE EFFECTS
1099 ============================================================================*/
1100void sap_compute_spect_weight(tSapChSelSpectInfo *pSpectInfoParams,
1101 tHalHandle halHandle, tScanResultHandle pResult,
1102 ptSapContext sap_ctx)
1103{
1104 int8_t rssi = 0;
1105 uint8_t chn_num = 0;
1106 uint8_t channel_id = 0;
1107
1108 tCsrScanResultInfo *pScanResult;
1109 tSapSpectChInfo *pSpectCh = pSpectInfoParams->pSpectCh;
1110 uint32_t operatingBand;
1111 uint16_t channelWidth;
1112 uint16_t secondaryChannelOffset;
1113 uint16_t centerFreq;
1114 uint16_t vhtSupport;
1115 uint32_t ieLen = 0;
1116 tSirProbeRespBeacon *pBeaconStruct;
1117 tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle;
1118
1119 pBeaconStruct = cdf_mem_malloc(sizeof(tSirProbeRespBeacon));
1120 if (NULL == pBeaconStruct) {
1121 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1122 "Unable to allocate memory in sap_compute_spect_weight\n");
1123 return;
1124 }
1125 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1126 "In %s, Computing spectral weight", __func__);
1127
1128 /**
1129 * Soft AP specific channel weight calculation using DFS formula
1130 */
1131 SET_ACS_BAND(operatingBand, sap_ctx);
1132
1133 pScanResult = sme_scan_result_get_first(halHandle, pResult);
1134
1135 while (pScanResult) {
1136 pSpectCh = pSpectInfoParams->pSpectCh;
1137 /* Defining the default values, so that any value will hold the default values */
1138 channelWidth = eHT_CHANNEL_WIDTH_20MHZ;
1139 secondaryChannelOffset = PHY_SINGLE_CHANNEL_CENTERED;
1140 vhtSupport = 0;
1141 centerFreq = 0;
1142
1143 if (pScanResult->BssDescriptor.ieFields != NULL) {
1144 ieLen =
1145 (pScanResult->BssDescriptor.length +
1146 sizeof(uint16_t) + sizeof(uint32_t) -
1147 sizeof(tSirBssDescription));
1148 cdf_mem_set((uint8_t *) pBeaconStruct,
1149 sizeof(tSirProbeRespBeacon), 0);
1150
1151 if ((sir_parse_beacon_ie
1152 (pMac, pBeaconStruct,
1153 (uint8_t *) (pScanResult->BssDescriptor.ieFields),
1154 ieLen)) == eSIR_SUCCESS) {
1155 sap_upd_chan_spec_params(pBeaconStruct,
1156 &channelWidth, &secondaryChannelOffset,
1157 &vhtSupport, &centerFreq);
1158 }
1159 }
1160 /* Processing for each tCsrScanResultInfo in the tCsrScanResult DLink list */
1161 for (chn_num = 0; chn_num < pSpectInfoParams->numSpectChans;
1162 chn_num++) {
1163
1164 /*
1165 * if the Beacon has channel ID, use it other wise we will
1166 * rely on the channelIdSelf
1167 */
1168 if (pScanResult->BssDescriptor.channelId == 0)
1169 channel_id =
1170 pScanResult->BssDescriptor.channelIdSelf;
1171 else
1172 channel_id =
1173 pScanResult->BssDescriptor.channelId;
1174
1175 if (pSpectCh && (channel_id == pSpectCh->chNum)) {
1176 if (pSpectCh->rssiAgr <
1177 pScanResult->BssDescriptor.rssi)
1178 pSpectCh->rssiAgr =
1179 pScanResult->BssDescriptor.rssi;
1180
1181 ++pSpectCh->bssCount; /* Increment the count of BSS */
1182
1183 /*
1184 * Connsidering the Extension Channel
1185 * only in a channels
1186 */
1187 switch (operatingBand) {
1188 case eCSR_DOT11_MODE_11a:
1189 sap_interference_rssi_count_5G(
1190 pSpectCh, channelWidth,
1191 secondaryChannelOffset, centerFreq,
1192 channel_id);
1193 break;
1194
1195 case eCSR_DOT11_MODE_11g:
1196 sap_interference_rssi_count(pSpectCh);
1197 break;
1198
1199 case eCSR_DOT11_MODE_abg:
1200 sap_interference_rssi_count_5G(
1201 pSpectCh, channelWidth,
1202 secondaryChannelOffset, centerFreq,
1203 channel_id);
1204 sap_interference_rssi_count(pSpectCh);
1205 break;
1206 }
1207
1208 CDF_TRACE(CDF_MODULE_ID_SAP,
1209 CDF_TRACE_LEVEL_INFO_HIGH,
1210 "In %s, bssdes.ch_self=%d, bssdes.ch_ID=%d, bssdes.rssi=%d, SpectCh.bssCount=%d, pScanResult=%p, ChannelWidth %d, secondaryChanOffset %d, center frequency %d \n",
1211 __func__,
1212 pScanResult->BssDescriptor.
1213 channelIdSelf,
1214 pScanResult->BssDescriptor.channelId,
1215 pScanResult->BssDescriptor.rssi,
1216 pSpectCh->bssCount, pScanResult,
1217 pSpectCh->channelWidth,
1218 secondaryChannelOffset, centerFreq);
1219 pSpectCh++;
1220 break;
1221 } else {
1222 pSpectCh++;
1223 }
1224 }
1225
1226 pScanResult = sme_scan_result_get_next(halHandle, pResult);
1227 }
1228
1229 /* Calculate the weights for all channels in the spectrum pSpectCh */
1230 pSpectCh = pSpectInfoParams->pSpectCh;
1231
1232 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1233 "In %s, Spectrum Channels Weight", __func__);
1234
1235 for (chn_num = 0; chn_num < (pSpectInfoParams->numSpectChans);
1236 chn_num++) {
1237
1238 /*
1239 rssi : Maximum received signal strength among all BSS on that channel
1240 bssCount : Number of BSS on that channel
1241 */
1242
1243 rssi = (int8_t) pSpectCh->rssiAgr;
1244 if (ch_in_pcl(sap_ctx, chn_num))
1245 rssi -= PCL_RSSI_DISCOUNT;
1246
1247 pSpectCh->weight =
1248 SAPDFS_NORMALISE_1000 * sapweight_rssi_count(rssi,
1249 pSpectCh->
1250 bssCount);
1251 pSpectCh->weight_copy = pSpectCh->weight;
1252
1253 /* ------ Debug Info ------ */
1254 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1255 "In %s, Chan=%d Weight= %d rssiAgr=%d bssCount=%d",
1256 __func__, pSpectCh->chNum, pSpectCh->weight,
1257 pSpectCh->rssiAgr, pSpectCh->bssCount);
1258 /* ------ Debug Info ------ */
1259 pSpectCh++;
1260 }
1261 cdf_mem_free(pBeaconStruct);
1262}
1263
1264/*==========================================================================
1265 FUNCTION sap_chan_sel_exit
1266
1267 DESCRIPTION
1268 Exit function for free out the allocated memory, to be called
1269 at the end of the dfsSelectChannel function
1270
1271 DEPENDENCIES
1272 NA.
1273
1274 PARAMETERS
1275
1276 IN
1277 pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure
1278
1279 RETURN VALUE
1280 void : NULL
1281
1282 SIDE EFFECTS
1283 ============================================================================*/
1284void sap_chan_sel_exit(tSapChSelSpectInfo *pSpectInfoParams)
1285{
1286 /* Free all the allocated memory */
1287 cdf_mem_free(pSpectInfoParams->pSpectCh);
1288}
1289
1290/*==========================================================================
1291 FUNCTION sap_sort_chl_weight
1292
1293 DESCRIPTION
1294 Funtion to sort the channels with the least weight first for 20MHz channels
1295
1296 DEPENDENCIES
1297 NA.
1298
1299 PARAMETERS
1300
1301 IN
1302 pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure
1303
1304 RETURN VALUE
1305 void : NULL
1306
1307 SIDE EFFECTS
1308 ============================================================================*/
1309void sap_sort_chl_weight(tSapChSelSpectInfo *pSpectInfoParams)
1310{
1311 tSapSpectChInfo temp;
1312
1313 tSapSpectChInfo *pSpectCh = NULL;
1314 uint32_t i = 0, j = 0, minWeightIndex = 0;
1315
1316 pSpectCh = pSpectInfoParams->pSpectCh;
1317 for (i = 0; i < pSpectInfoParams->numSpectChans; i++) {
1318 minWeightIndex = i;
1319 for (j = i + 1; j < pSpectInfoParams->numSpectChans; j++) {
1320 if (pSpectCh[j].weight <
1321 pSpectCh[minWeightIndex].weight) {
1322 minWeightIndex = j;
1323 }
1324 }
1325 if (minWeightIndex != i) {
1326 cdf_mem_copy(&temp, &pSpectCh[minWeightIndex],
1327 sizeof(*pSpectCh));
1328 cdf_mem_copy(&pSpectCh[minWeightIndex], &pSpectCh[i],
1329 sizeof(*pSpectCh));
1330 cdf_mem_copy(&pSpectCh[i], &temp, sizeof(*pSpectCh));
1331 }
1332 }
1333}
1334
1335/**
1336 * sap_sort_chl_weight_ht80() - to sort the channels with the least weight
1337 * @pSpectInfoParams: Pointer to the tSapChSelSpectInfo structure
1338 *
1339 * Funtion to sort the channels with the least weight first for HT80 channels
1340 *
1341 * Return: none
1342 */
1343void sap_sort_chl_weight_ht80(tSapChSelSpectInfo *pSpectInfoParams)
1344{
1345 uint8_t i, j, n;
1346 tSapSpectChInfo *pSpectInfo;
1347 uint8_t minIdx;
1348
1349 pSpectInfo = pSpectInfoParams->pSpectCh;
1350 /* for each HT80 channel, calculate the combined weight of the
1351 four 20MHz weight */
1352 for (i = 0; i < ARRAY_SIZE(acs_ht80_channels); i++) {
1353 for (j = 0; j < pSpectInfoParams->numSpectChans; j++) {
1354 if (pSpectInfo[j].chNum ==
1355 acs_ht80_channels[i].chStartNum)
1356 break;
1357 }
1358 if (j == pSpectInfoParams->numSpectChans)
1359 continue;
1360
1361 if (!(((pSpectInfo[j].chNum + 4) == pSpectInfo[j + 1].chNum) &&
1362 ((pSpectInfo[j].chNum + 8) ==
1363 pSpectInfo[j + 2].chNum) &&
1364 ((pSpectInfo[j].chNum + 12) ==
1365 pSpectInfo[j + 3].chNum))) {
1366 /*
1367 * some channels does not exist in pSectInfo array,
1368 * skip this channel and those in the same HT80 width
1369 */
1370 pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 4;
1371 if ((pSpectInfo[j].chNum + 4) ==
1372 pSpectInfo[j + 1].chNum)
1373 pSpectInfo[j + 1].weight =
1374 SAP_ACS_WEIGHT_MAX * 4;
1375 if ((pSpectInfo[j].chNum + 8) ==
1376 pSpectInfo[j + 2].chNum)
1377 pSpectInfo[j + 2].weight =
1378 SAP_ACS_WEIGHT_MAX * 4;
1379 if ((pSpectInfo[j].chNum + 12) ==
1380 pSpectInfo[j + 3].chNum)
1381 pSpectInfo[j + 3].weight =
1382 SAP_ACS_WEIGHT_MAX * 4;
1383 continue;
1384 }
1385 /*found the channel, add the 4 adjacent channels' weight */
1386 acs_ht80_channels[i].weight = pSpectInfo[j].weight +
1387 pSpectInfo[j + 1].weight + pSpectInfo[j + 2].weight +
1388 pSpectInfo[j + 3].weight;
1389 /* find best channel among 4 channels as the primary channel */
1390 if ((pSpectInfo[j].weight + pSpectInfo[j + 1].weight) <
1391 (pSpectInfo[j + 2].weight + pSpectInfo[j + 3].weight)) {
1392 /* lower 2 channels are better choice */
1393 if (pSpectInfo[j].weight < pSpectInfo[j + 1].weight)
1394 minIdx = 0;
1395 else
1396 minIdx = 1;
1397 } else if (pSpectInfo[j + 2].weight <=
1398 pSpectInfo[j + 3].weight) {
1399 /* upper 2 channels are better choice */
1400 minIdx = 2;
1401 } else {
1402 minIdx = 3;
1403 }
1404
1405 /*
1406 * set all 4 channels to max value first, then reset the
1407 * best channel as the selected primary channel, update its
1408 * weightage with the combined weight value
1409 */
1410 for (n = 0; n < 4; n++)
1411 pSpectInfo[j + n].weight = SAP_ACS_WEIGHT_MAX * 4;
1412
1413 pSpectInfo[j + minIdx].weight = acs_ht80_channels[i].weight;
1414 }
1415
1416 pSpectInfo = pSpectInfoParams->pSpectCh;
1417 for (j = 0; j < pSpectInfoParams->numSpectChans; j++) {
1418 if (CHANNEL_165 == pSpectInfo[j].chNum) {
1419 pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 4;
1420 break;
1421 }
1422 }
1423
1424 pSpectInfo = pSpectInfoParams->pSpectCh;
1425 for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) {
1426 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1427 FL("Channel=%d Weight= %d rssi=%d bssCount=%d"),
1428 pSpectInfo->chNum, pSpectInfo->weight,
1429 pSpectInfo->rssiAgr, pSpectInfo->bssCount);
1430 pSpectInfo++;
1431 }
1432}
1433
1434/**
1435 * sap_sort_chl_weight_ht40_24_g() - to sort channel with the least weight
1436 * @pSpectInfoParams: Pointer to the tSapChSelSpectInfo structure
1437 *
1438 * Funtion to sort the channels with the least weight first for HT40 channels
1439 *
1440 * Return: none
1441 */
1442void sap_sort_chl_weight_ht40_24_g(tSapChSelSpectInfo *pSpectInfoParams)
1443{
1444 uint8_t i, j;
1445 tSapSpectChInfo *pSpectInfo;
1446 uint32_t tmpWeight1, tmpWeight2;
1447
1448 pSpectInfo = pSpectInfoParams->pSpectCh;
1449 /*
1450 * for each HT40 channel, calculate the combined weight of the
1451 * two 20MHz weight
1452 */
1453 for (i = 0; i < ARRAY_SIZE(acs_ht40_channels24_g); i++) {
1454 for (j = 0; j < pSpectInfoParams->numSpectChans; j++) {
1455 if (pSpectInfo[j].chNum ==
1456 acs_ht40_channels24_g[i].chStartNum)
1457 break;
1458 }
1459 if (j == pSpectInfoParams->numSpectChans)
1460 continue;
1461
1462 if (!((pSpectInfo[j].chNum + 4) == pSpectInfo[j + 4].chNum)) {
1463 pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 2;
1464 continue;
1465 }
1466 /*
1467 * check if there is another channel combination possiblity
1468 * e.g., {1, 5} & {5, 9}
1469 */
1470 if ((pSpectInfo[j + 4].chNum + 4) == pSpectInfo[j + 8].chNum) {
1471 /* need to compare two channel pairs */
1472 tmpWeight1 = pSpectInfo[j].weight +
1473 pSpectInfo[j + 4].weight;
1474 tmpWeight2 = pSpectInfo[j + 4].weight +
1475 pSpectInfo[j + 8].weight;
1476 if (tmpWeight1 <= tmpWeight2) {
1477 if (pSpectInfo[j].weight <=
1478 pSpectInfo[j + 4].weight) {
1479 pSpectInfo[j].weight =
1480 tmpWeight1;
1481 pSpectInfo[j + 4].weight =
1482 SAP_ACS_WEIGHT_MAX * 2;
1483 pSpectInfo[j + 8].weight =
1484 SAP_ACS_WEIGHT_MAX * 2;
1485 } else {
1486 pSpectInfo[j + 4].weight =
1487 tmpWeight1;
1488 /* for secondary channel selection */
1489 pSpectInfo[j].weight =
1490 SAP_ACS_WEIGHT_MAX * 2
1491 - 1;
1492 pSpectInfo[j + 8].weight =
1493 SAP_ACS_WEIGHT_MAX * 2;
1494 }
1495 } else {
1496 if (pSpectInfo[j + 4].weight <=
1497 pSpectInfo[j + 8].weight) {
1498 pSpectInfo[j + 4].weight =
1499 tmpWeight2;
1500 pSpectInfo[j].weight =
1501 SAP_ACS_WEIGHT_MAX * 2;
1502 /* for secondary channel selection */
1503 pSpectInfo[j + 8].weight =
1504 SAP_ACS_WEIGHT_MAX * 2
1505 - 1;
1506 } else {
1507 pSpectInfo[j + 8].weight =
1508 tmpWeight2;
1509 pSpectInfo[j].weight =
1510 SAP_ACS_WEIGHT_MAX * 2;
1511 pSpectInfo[j + 4].weight =
1512 SAP_ACS_WEIGHT_MAX * 2;
1513 }
1514 }
1515 } else {
1516 tmpWeight1 = pSpectInfo[j].weight +
1517 pSpectInfo[j + 4].weight;
1518 if (pSpectInfo[j].weight <=
1519 pSpectInfo[j + 4].weight) {
1520 pSpectInfo[j].weight = tmpWeight1;
1521 pSpectInfo[j + 4].weight =
1522 SAP_ACS_WEIGHT_MAX * 2;
1523 } else {
1524 pSpectInfo[j + 4].weight = tmpWeight1;
1525 pSpectInfo[j].weight =
1526 SAP_ACS_WEIGHT_MAX * 2;
1527 }
1528 }
1529 }
1530}
1531
1532/*==========================================================================
1533 FUNCTION sap_sort_chl_weight_ht40_5_g
1534
1535 DESCRIPTION
1536 Funtion to sort the channels with the least weight first for HT40 channels
1537
1538 DEPENDENCIES
1539 NA.
1540
1541 PARAMETERS
1542
1543 IN
1544 pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure
1545
1546 RETURN VALUE
1547 void : NULL
1548
1549 SIDE EFFECTS
1550 ============================================================================*/
1551void sap_sort_chl_weight_ht40_5_g(tSapChSelSpectInfo *pSpectInfoParams)
1552{
1553 uint8_t i, j;
1554 tSapSpectChInfo *pSpectInfo;
1555
1556 pSpectInfo = pSpectInfoParams->pSpectCh;
1557 /*for each HT40 channel, calculate the combined weight of the
1558 two 20MHz weight */
1559 for (i = 0; i < ARRAY_SIZE(acs_ht40_channels5_g); i++) {
1560 for (j = 0; j < pSpectInfoParams->numSpectChans; j++) {
1561 if (pSpectInfo[j].chNum ==
1562 acs_ht40_channels5_g[i].chStartNum)
1563 break;
1564 }
1565 if (j == pSpectInfoParams->numSpectChans)
1566 continue;
1567
1568 /* found the channel, add the two adjacent channels' weight */
1569 if ((pSpectInfo[j].chNum + 4) == pSpectInfo[j + 1].chNum) {
1570 acs_ht40_channels5_g[i].weight = pSpectInfo[j].weight +
1571 pSpectInfo[j + 1].weight;
1572 /* select better of the adjact channel as the primary channel */
1573 if (pSpectInfo[j].weight <= pSpectInfo[j + 1].weight) {
1574 pSpectInfo[j].weight =
1575 acs_ht40_channels5_g[i].weight;
1576 /* mark the adjacent channel's weight as max value so
1577 that it will be sorted to the bottom */
1578 pSpectInfo[j + 1].weight =
1579 SAP_ACS_WEIGHT_MAX * 2;
1580 } else {
1581 pSpectInfo[j + 1].weight =
1582 acs_ht40_channels5_g[i].weight;
1583 /* mark the adjacent channel's weight as max value so
1584 that it will be sorted to the bottom */
1585 pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 2;
1586 }
1587
1588 } else
1589 pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 2;
1590 }
1591
1592 /* avoid channel 165 by setting its weight to max */
1593 pSpectInfo = pSpectInfoParams->pSpectCh;
1594 for (j = 0; j < pSpectInfoParams->numSpectChans; j++) {
1595 if (CHANNEL_165 == pSpectInfo[j].chNum) {
1596 pSpectInfo[j].weight = SAP_ACS_WEIGHT_MAX * 2;
1597 break;
1598 }
1599 }
1600
1601 pSpectInfo = pSpectInfoParams->pSpectCh;
1602 for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) {
1603 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1604 "In %s, Channel=%d Weight= %d rssi=%d bssCount=%d",
1605 __func__, pSpectInfo->chNum, pSpectInfo->weight,
1606 pSpectInfo->rssiAgr, pSpectInfo->bssCount);
1607 pSpectInfo++;
1608 }
1609
1610 sap_sort_chl_weight(pSpectInfoParams);
1611}
1612
1613/*==========================================================================
1614 FUNCTION sap_sort_chl_weight_all
1615
1616 DESCRIPTION
1617 Funtion to sort the channels with the least weight first
1618
1619 DEPENDENCIES
1620 NA.
1621
1622 PARAMETERS
1623
1624 IN
1625 ptSapContext : Pointer to the ptSapContext structure
1626 pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure
1627
1628 RETURN VALUE
1629 void : NULL
1630
1631 SIDE EFFECTS
1632 ============================================================================*/
1633void sap_sort_chl_weight_all(ptSapContext pSapCtx,
1634 tSapChSelSpectInfo *pSpectInfoParams,
1635 uint32_t operatingBand)
1636{
1637 tSapSpectChInfo *pSpectCh = NULL;
1638 uint32_t j = 0;
1639#ifndef SOFTAP_CHANNEL_RANGE
1640 uint32_t i = 0;
1641#endif
1642
1643 pSpectCh = pSpectInfoParams->pSpectCh;
1644#ifdef SOFTAP_CHANNEL_RANGE
1645
1646 switch (pSapCtx->acs_cfg->ch_width) {
1647 case CH_WIDTH_40MHZ:
1648 if (eCSR_DOT11_MODE_11g == operatingBand)
1649 sap_sort_chl_weight_ht40_24_g(pSpectInfoParams);
1650 else if (eCSR_DOT11_MODE_11a == operatingBand)
1651 sap_sort_chl_weight_ht40_5_g(pSpectInfoParams);
1652 else {
1653 sap_sort_chl_weight_ht40_24_g(pSpectInfoParams);
1654 sap_sort_chl_weight_ht40_5_g(pSpectInfoParams);
1655 }
1656 sap_sort_chl_weight(pSpectInfoParams);
1657 break;
1658
1659 case CH_WIDTH_80MHZ:
1660 sap_sort_chl_weight_ht80(pSpectInfoParams);
1661 break;
1662
1663 case CH_WIDTH_20MHZ:
1664 default:
1665 /* Sorting the channels as per weights as 20MHz channels */
1666 sap_sort_chl_weight(pSpectInfoParams);
1667 }
1668
1669#else
1670 /* Sorting the channels as per weights */
1671 for (i = 0; i < SPECT_24GHZ_CH_COUNT; i++) {
1672 minWeightIndex = i;
1673 for (j = i + 1; j < SPECT_24GHZ_CH_COUNT; j++) {
1674 if (pSpectCh[j].weight <
1675 pSpectCh[minWeightIndex].weight) {
1676 minWeightIndex = j;
1677 }
1678 }
1679 if (minWeightIndex != i) {
1680 cdf_mem_copy(&temp, &pSpectCh[minWeightIndex],
1681 sizeof(*pSpectCh));
1682 cdf_mem_copy(&pSpectCh[minWeightIndex], &pSpectCh[i],
1683 sizeof(*pSpectCh));
1684 cdf_mem_copy(&pSpectCh[i], &temp, sizeof(*pSpectCh));
1685 }
1686 }
1687#endif
1688
1689 /* For testing */
1690 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1691 "In %s, Sorted Spectrum Channels Weight", __func__);
1692 pSpectCh = pSpectInfoParams->pSpectCh;
1693 for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) {
1694 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1695 "In %s, Channel=%d Weight= %d rssi=%d bssCount=%d",
1696 __func__, pSpectCh->chNum, pSpectCh->weight,
1697 pSpectCh->rssiAgr, pSpectCh->bssCount);
1698 pSpectCh++;
1699 }
1700
1701}
1702
1703/*==========================================================================
1704 FUNCTION sap_filter_over_lap_ch
1705
1706 DESCRIPTION
1707 return true if ch is acceptable.
1708 This function will decide if we will filter over lap channel or not.
1709
1710 DEPENDENCIES
1711 shall called after ap start.
1712
1713 PARAMETERS
1714
1715 IN
1716 pSapCtx : Pointer to ptSapContext.
1717 chNum : Filter channel number.
1718
1719 RETURN VALUE
1720 bool : true if channel is accepted.
1721
1722 SIDE EFFECTS
1723 ============================================================================*/
1724bool sap_filter_over_lap_ch(ptSapContext pSapCtx, uint16_t chNum)
1725{
1726 if (pSapCtx->enableOverLapCh)
1727 return eSAP_TRUE;
1728 else if ((chNum == CHANNEL_1) ||
1729 (chNum == CHANNEL_6) || (chNum == CHANNEL_11))
1730 return eSAP_TRUE;
1731
1732 return eSAP_FALSE;
1733}
1734
1735/*==========================================================================
1736 FUNCTION sap_select_channel
1737
1738 DESCRIPTION
1739 Runs a algorithm to select the best channel to operate in based on BSS
1740 rssi and bss count on each channel
1741
1742 DEPENDENCIES
1743 NA.
1744
1745 PARAMETERS
1746
1747 IN
1748 halHandle : Pointer to HAL handle
1749 pResult : Pointer to tScanResultHandle
1750
1751 RETURN VALUE
1752 uint8_t : Success - channel number, Fail - zero
1753
1754 SIDE EFFECTS
1755 ============================================================================*/
1756uint8_t sap_select_channel(tHalHandle halHandle, ptSapContext pSapCtx,
1757 tScanResultHandle pScanResult)
1758{
1759 /* DFS param object holding all the data req by the algo */
1760 tSapChSelSpectInfo oSpectInfoParams = { NULL, 0 };
1761 tSapChSelSpectInfo *pSpectInfoParams = &oSpectInfoParams; /* Memory? NB */
1762 uint8_t bestChNum = SAP_CHANNEL_NOT_SELECTED;
1763#ifdef FEATURE_WLAN_CH_AVOID
1764 uint8_t i;
1765 uint8_t firstSafeChannelInRange = SAP_CHANNEL_NOT_SELECTED;
1766#endif
1767#ifdef SOFTAP_CHANNEL_RANGE
1768 uint32_t startChannelNum;
1769 uint32_t endChannelNum;
1770 uint32_t operatingBand = 0;
1771 uint32_t tmpChNum;
1772 uint8_t count;
1773#endif
1774 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1775 "In %s, Running SAP Ch Select", __func__);
1776
1777#ifdef FEATURE_WLAN_CH_AVOID
1778 sap_update_unsafe_channel_list(pSapCtx);
1779#endif
1780
1781 if (NULL == pScanResult) {
1782 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1783 "%s: No external AP present\n", __func__);
1784
1785#ifndef SOFTAP_CHANNEL_RANGE
1786 return bestChNum;
1787#else
1788 startChannelNum = pSapCtx->acs_cfg->start_ch;
1789 endChannelNum = pSapCtx->acs_cfg->end_ch;
1790
1791
1792 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
1793 "%s: start - end: %d - %d\n", __func__,
1794 startChannelNum, endChannelNum);
1795
1796#ifndef FEATURE_WLAN_CH_AVOID /* FEATURE_WLAN_CH_AVOID NOT defined case */
1797 pSapCtx->acs_cfg->pri_ch = startChannelNum;
1798 pSapCtx->acs_cfg->ht_sec_ch = 0;
1799 /* pick the first channel in configured range */
1800 return startChannelNum;
1801#else /* FEATURE_WLAN_CH_AVOID defined */
1802
1803 /* get a channel in PCL and within the range */
1804 for (i = 0; i < pSapCtx->acs_cfg->pcl_ch_count; i++) {
1805 if ((pSapCtx->acs_cfg->pcl_channels[i] >=
1806 startChannelNum)
1807 && (pSapCtx->acs_cfg->pcl_channels[i] <=
1808 endChannelNum)) {
1809 firstSafeChannelInRange =
1810 pSapCtx->acs_cfg->pcl_channels[i];
1811 break;
1812 }
1813 }
1814 if (SAP_CHANNEL_NOT_SELECTED != firstSafeChannelInRange)
1815 return firstSafeChannelInRange;
1816
1817 for (i = 0; i < NUM_20MHZ_RF_CHANNELS; i++) {
1818 if ((safe_channels[i].channelNumber >= startChannelNum)
1819 && (safe_channels[i].channelNumber <=
1820 endChannelNum)) {
1821 CHANNEL_STATE channel_type =
1822 cds_get_channel_state(safe_channels[i].
1823 channelNumber);
1824
1825 if ((channel_type == CHANNEL_STATE_DISABLE) ||
1826 (channel_type == CHANNEL_STATE_INVALID))
1827 continue;
1828
1829 if (safe_channels[i].isSafe == true) {
1830 CDF_TRACE(CDF_MODULE_ID_SAP,
1831 CDF_TRACE_LEVEL_INFO_HIGH,
1832 "%s: channel %d in the configuration is safe\n",
1833 __func__,
1834 safe_channels[i].
1835 channelNumber);
1836 firstSafeChannelInRange =
1837 safe_channels[i].channelNumber;
1838 break;
1839 }
1840
1841 CDF_TRACE(CDF_MODULE_ID_SAP,
1842 CDF_TRACE_LEVEL_INFO_HIGH,
1843 "%s: channel %d in the configuration is unsafe\n",
1844 __func__,
1845 safe_channels[i].channelNumber);
1846 }
1847 }
1848
1849 /* if no channel selected return SAP_CHANNEL_NOT_SELECTED */
1850 return firstSafeChannelInRange;
1851#endif /* !FEATURE_WLAN_CH_AVOID */
1852#endif /* SOFTAP_CHANNEL_RANGE */
1853 }
1854
1855 /* Initialize the structure pointed by pSpectInfoParams */
1856 if (sap_chan_sel_init(halHandle, pSpectInfoParams, pSapCtx) != eSAP_TRUE) {
1857 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_ERROR,
1858 "In %s, Ch Select initialization failed", __func__);
1859 return SAP_CHANNEL_NOT_SELECTED;
1860 }
1861 /* Compute the weight of the entire spectrum in the operating band */
1862 sap_compute_spect_weight(pSpectInfoParams, halHandle, pScanResult,
1863 pSapCtx);
1864
1865#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
1866 /* process avoid channel IE to collect all channels to avoid */
1867 sap_process_avoid_ie(halHandle, pSapCtx, pScanResult, pSpectInfoParams);
1868#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
1869
1870#ifdef SOFTAP_CHANNEL_RANGE
1871 startChannelNum = pSapCtx->acs_cfg->start_ch;
1872 endChannelNum = pSapCtx->acs_cfg->end_ch;
1873 SET_ACS_BAND(operatingBand, pSapCtx);
1874
1875 pSapCtx->acsBestChannelInfo.channelNum = 0;
1876 pSapCtx->acsBestChannelInfo.weight = SAP_ACS_WEIGHT_MAX;
1877
1878 /* Sort the channel list as per the computed weights, lesser weight first. */
1879 sap_sort_chl_weight_all(pSapCtx, pSpectInfoParams, operatingBand);
1880
1881 /*Loop till get the best channel in the given range */
1882 for (count = 0; count < pSpectInfoParams->numSpectChans; count++) {
1883 if ((startChannelNum <= pSpectInfoParams->pSpectCh[count].chNum)
1884 && (endChannelNum >=
1885 pSpectInfoParams->pSpectCh[count].chNum)) {
1886 if (bestChNum == SAP_CHANNEL_NOT_SELECTED) {
1887 bestChNum =
1888 pSpectInfoParams->pSpectCh[count].chNum;
1889 /* check if bestChNum is in preferred channel list */
1890 bestChNum =
1891 sap_select_preferred_channel_from_channel_list
1892 (bestChNum, pSapCtx, pSpectInfoParams);
1893 if (bestChNum == SAP_CHANNEL_NOT_SELECTED) {
1894 /* not in preferred channel list, go to next best channel */
1895 continue;
1896 }
1897
1898#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
1899 /* Weight of the channels(device's AP is
1900 * operating) increased to MAX+1 so that they
1901 * will be choosen only when there is no other
1902 * best channel to choose
1903 */
1904 if (sap_check_in_avoid_ch_list(pSapCtx,
1905 bestChNum)) {
1906 bestChNum = SAP_CHANNEL_NOT_SELECTED;
1907 continue;
1908 }
1909#endif
1910
1911 pSapCtx->acsBestChannelInfo.channelNum =
1912 bestChNum;
1913 pSapCtx->acsBestChannelInfo.weight =
1914 pSpectInfoParams->
1915 pSpectCh[count].
1916 weight_copy;
1917 }
1918
1919 if (bestChNum != SAP_CHANNEL_NOT_SELECTED) {
1920 if (operatingBand == eCSR_DOT11_MODE_11g) {
1921 /* Give preference to Non-overlap channels */
1922 if (sap_filter_over_lap_ch(pSapCtx,
1923 pSpectInfoParams->
1924 pSpectCh[count].
1925 chNum)) {
1926 tmpChNum =
1927 pSpectInfoParams->
1928 pSpectCh[count].chNum;
1929 tmpChNum =
1930 sap_select_preferred_channel_from_channel_list
1931 (tmpChNum, pSapCtx,
1932 pSpectInfoParams);
1933 if (tmpChNum !=
1934 SAP_CHANNEL_NOT_SELECTED) {
1935 bestChNum = tmpChNum;
1936 break;
1937 }
1938 }
1939 }
1940 }
1941 }
1942 }
1943#else
1944 /* Sort the channel list as per the computed weights, lesser weight first. */
1945 sap_sort_chl_weight_all(pSapCtx, halHandle, pSpectInfoParams);
1946 /* Get the first channel in sorted array as best 20M Channel */
1947 bestChNum = (uint8_t) pSpectInfoParams->pSpectCh[0].chNum;
1948 /* Select Best Channel from Channel List if Configured */
1949 bestChNum = sap_select_preferred_channel_from_channel_list(bestChNum,
1950 pSapCtx,
1951 pSpectInfoParams);
1952#endif
1953
1954 /** in case the best channel seleted is not in PCL and there is another
1955 * channel which has same weightage and is in PCL, choose the one in
1956 * PCL
1957 */
1958 for (count = 0; count < pSpectInfoParams->numSpectChans; count++) {
1959 /** check if a pcl channel has the same weightage
1960 * as the best channel
1961 */
1962 if (ch_in_pcl(pSapCtx, pSpectInfoParams->pSpectCh[count].chNum)
1963 && (pSpectInfoParams->pSpectCh[count].weight ==
1964 pSapCtx->acsBestChannelInfo.weight)) {
1965 if (sap_select_preferred_channel_from_channel_list(
1966 pSpectInfoParams->pSpectCh[count].chNum,
1967 pSapCtx, pSpectInfoParams) ==
1968 SAP_CHANNEL_NOT_SELECTED)
1969 continue;
1970
1971#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
1972 if (sap_check_in_avoid_ch_list(pSapCtx, bestChNum))
1973 continue;
1974#endif
1975 bestChNum = pSpectInfoParams->pSpectCh[count].chNum;
1976 CDF_TRACE(CDF_MODULE_ID_SAP,
1977 CDF_TRACE_LEVEL_INFO_HIGH,
1978 "change best channel to %d in PCL",
1979 bestChNum);
1980 break;
1981 }
1982 }
1983
1984 pSapCtx->acs_cfg->pri_ch = bestChNum;
1985 /* determine secondary channel for 2.4G channel 5, 6, 7 in HT40 */
1986 if ((operatingBand == eCSR_DOT11_MODE_11g) &&
1987 (pSapCtx->acs_cfg->ch_width == CH_WIDTH_40MHZ)) {
1988 if ((bestChNum >= 5) && (bestChNum <= 7)) {
1989 int weight_below, weight_above, i;
1990 tSapSpectChInfo *pspect_info;
1991
1992 weight_below = weight_above = SAP_ACS_WEIGHT_MAX;
1993 pspect_info = pSpectInfoParams->pSpectCh;
1994 for (i = 0; i < pSpectInfoParams->numSpectChans;
1995 i++) {
1996 if (pspect_info[i].chNum == (bestChNum - 4))
1997 weight_below = pspect_info[i].weight;
1998
1999 if (pspect_info[i].chNum == (bestChNum + 4))
2000 weight_above = pspect_info[i].weight;
2001 }
2002
2003 if (weight_below < weight_above)
2004 pSapCtx->acs_cfg->ht_sec_ch =
2005 pSapCtx->acs_cfg->pri_ch - 4;
2006 else
2007 pSapCtx->acs_cfg->ht_sec_ch =
2008 pSapCtx->acs_cfg->pri_ch + 4;
2009 } else if (bestChNum >= 1 && bestChNum <= 4) {
2010 pSapCtx->acs_cfg->ht_sec_ch =
2011 pSapCtx->acs_cfg->pri_ch + 4;
2012 } else if (bestChNum >= 8 && bestChNum <= 13) {
2013 pSapCtx->acs_cfg->ht_sec_ch =
2014 pSapCtx->acs_cfg->pri_ch - 4;
2015 } else if (bestChNum == 14) {
2016 pSapCtx->acs_cfg->ht_sec_ch = 0;
2017 }
2018 pSapCtx->secondary_ch = pSapCtx->acs_cfg->ht_sec_ch;
2019 }
2020 /* Free all the allocated memory */
2021 sap_chan_sel_exit(pSpectInfoParams);
2022
2023 CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO_HIGH,
2024 "In %s, Running SAP Ch select Completed, Ch=%d", __func__,
2025 bestChNum);
2026 if (bestChNum > 0 && bestChNum <= 252)
2027 return bestChNum;
2028 else
2029 return SAP_CHANNEL_NOT_SELECTED;
2030}