blob: 9d4a012b766e6674ddb9e4eff612bb7d324cf2c2 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Jeff Johnson32d95a32012-09-10 13:15:23 -07002 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -07003 *
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
24 s a p C h S e l e c t . C
25
26 OVERVIEW:
27
28 This software unit holds the implementation of the WLAN SAP modules
29 functions for channel selection.
30
31 DEPENDENCIES:
32
33 Are listed for each API below.
34
35
36 Copyright (c) 2010 QUALCOMM Incorporated.
37 All Rights Reserved.
38 Qualcomm Confidential and Proprietary
39===========================================================================*/
40
41/*===========================================================================
42
43 EDIT HISTORY FOR FILE
44
45
46 This section contains comments describing changes made to the module.
47 Notice that changes are listed in reverse chronological order.
48
49
50
51 when who what, where, why
52---------- --- --------------------------------------------------------
532010-03-15 SOFTAP Created module
54
55===========================================================================*/
56
57
58/*--------------------------------------------------------------------------
59 Include Files
60------------------------------------------------------------------------*/
61#include "vos_trace.h"
62#include "csrApi.h"
63#include "sme_Api.h"
64#include "sapChSelect.h"
65#include "sapInternal.h"
66
67/*--------------------------------------------------------------------------
68 Function definitions
69--------------------------------------------------------------------------*/
70
71/*--------------------------------------------------------------------------
72 Defines
73--------------------------------------------------------------------------*/
74#define SAP_DEBUG
75
76/*==========================================================================
77 FUNCTION sapChanSelInit
78
79 DESCRIPTION
80 Function sapChanSelInit allocates the memory, intializes the
81 structures used by the channel selection algorithm
82
83 DEPENDENCIES
84 NA.
85
86 PARAMETERS
87
88 IN
89 *pSpectInfoParams : Pointer to tSapChSelSpectInfo structure
90
91 RETURN VALUE
92 v_BOOL_t: Success or FAIL
93
94 SIDE EFFECTS
95============================================================================*/
96v_BOOL_t sapChanSelInit(tHalHandle halHandle, tSapChSelSpectInfo *pSpectInfoParams)
97{
98 tSapSpectChInfo *pSpectCh = NULL;
99 v_U8_t *pChans = NULL;
100 v_U16_t channelnum = 0;
101 tpAniSirGlobal pMac = PMAC_STRUCT(halHandle);
102
103 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s", __FUNCTION__);
104
105 // Channels for that 2.4GHz band
106 //Considered only for 2.4GHz need to change in future to support 5GHz support
107 pSpectInfoParams->numSpectChans = pMac->scan.base20MHzChannels.numChannels;
108
109 // Allocate memory for weight computation of 2.4GHz
110 pSpectCh = (tSapSpectChInfo *)vos_mem_malloc((pSpectInfoParams->numSpectChans) * sizeof(*pSpectCh));
111
112 if(pSpectCh == NULL) {
113 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, VOS_MALLOC_ERR", __FUNCTION__);
114 return eSAP_FALSE;
115 }
116
117 vos_mem_zero(pSpectCh, (pSpectInfoParams->numSpectChans) * sizeof(*pSpectCh));
118
119 // Initialize the pointers in the DfsParams to the allocated memory
120 pSpectInfoParams->pSpectCh = pSpectCh;
121
122 pChans = pMac->scan.base20MHzChannels.channelList;
123
124 // Fill the channel number in the spectrum in the operating freq band
125 for (channelnum = 0; channelnum < pSpectInfoParams->numSpectChans; channelnum++) {
126
127 if(*pChans == 14 ) //OFDM rates are not supported on channel 14
128 continue;
129 pSpectCh->chNum = *pChans;
130 pSpectCh->valid = eSAP_TRUE;
131 pSpectCh->rssiAgr = SOFTAP_MIN_RSSI;// Initialise for all channels
132 pSpectCh++;
133 pChans++;
134 }
135 return eSAP_TRUE;
136}
137
138/*==========================================================================
139 FUNCTION sapweightRssiCount
140
141 DESCRIPTION
142 Function weightRssiCount calculates the channel weight due to rssi
143 and data count(here number of BSS observed)
144
145 DEPENDENCIES
146 NA.
147
148 PARAMETERS
149
150 IN
151 rssi : Max signal strength receieved from a BSS for the channel
152 count : Number of BSS observed in the channel
153
154 RETURN VALUE
155 v_U32_t : Calculated channel weight based on above two
156
157 SIDE EFFECTS
158============================================================================*/
159v_U32_t sapweightRssiCount(v_S7_t rssi, v_U16_t count)
160{
161 v_S31_t rssiWeight=0;
162 v_S31_t countWeight=0;
163 v_U32_t rssicountWeight=0;
164
165 // Weight from RSSI
166 rssiWeight = SOFTAP_RSSI_WEIGHT * (rssi - SOFTAP_MIN_RSSI)
167 /(SOFTAP_MAX_RSSI - SOFTAP_MIN_RSSI);
168
169 if(rssiWeight > SOFTAP_RSSI_WEIGHT)
170 rssiWeight = SOFTAP_RSSI_WEIGHT;
171 else if (rssiWeight < 0)
172 rssiWeight = 0;
173
174 // Weight from data count
175 countWeight = SOFTAP_COUNT_WEIGHT * (count - SOFTAP_MIN_COUNT)
176 /(SOFTAP_MAX_COUNT - SOFTAP_MIN_COUNT);
177
178 if(countWeight > SOFTAP_COUNT_WEIGHT)
179 countWeight = SOFTAP_COUNT_WEIGHT;
180 else if (countWeight < 0)
181 countWeight = 0;
182
183 rssicountWeight = rssiWeight + countWeight;
184
185 VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, rssiWeight=%d, countWeight=%d, rssicountWeight=%d",
186 __FUNCTION__, rssiWeight, countWeight, rssicountWeight);
187
188 return(rssicountWeight);
189}
190
191/*==========================================================================
192 FUNCTION sapComputeSpectWeight
193
194 DESCRIPTION
195 Main function for computing the weight of each channel in the
196 spectrum based on the RSSI value of the BSSes on the channel
197 and number of BSS
198
199 DEPENDENCIES
200 NA.
201
202 PARAMETERS
203
204 IN
205 pSpectInfoParams : Pointer to the tSpectInfoParams structure
206 halHandle : Pointer to HAL handle
207 pResult : Pointer to tScanResultHandle
208
209 RETURN VALUE
210 void : NULL
211
212 SIDE EFFECTS
213============================================================================*/
214void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams,
215 tHalHandle halHandle, tScanResultHandle pResult)
216{
217 v_S7_t rssi = 0;
218 v_U8_t chn_num = 0;
219 v_U8_t channel_id = 0;
220
221 tCsrScanResultInfo *pScanResult;
222 tSapSpectChInfo *pSpectCh = pSpectInfoParams->pSpectCh;
223
224 VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Computing spectral weight", __FUNCTION__);
225
226 /**
227 * Soft AP specific channel weight calculation using DFS formula
228 */
229
230 pScanResult = sme_ScanResultGetFirst(halHandle, pResult);
231
232 while (pScanResult) {
233 pSpectCh = pSpectInfoParams->pSpectCh;
234 // Processing for each tCsrScanResultInfo in the tCsrScanResult DLink list
235 for (chn_num = 0; chn_num < pSpectInfoParams->numSpectChans; chn_num++) {
236
237 /*
238 * if the Beacon has channel ID, use it other wise we will
239 * rely on the channelIdSelf
240 */
241 if(pScanResult->BssDescriptor.channelId == 0)
242 channel_id = pScanResult->BssDescriptor.channelIdSelf;
243 else
244 channel_id = pScanResult->BssDescriptor.channelId;
245
246 if (channel_id == pSpectCh->chNum) {
247 if (pSpectCh->rssiAgr < pScanResult->BssDescriptor.rssi)
248 pSpectCh->rssiAgr = pScanResult->BssDescriptor.rssi;
249
250 ++pSpectCh->bssCount; // Increment the count of BSS
251
252 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH,
253 "In %s, bssdes.ch_self=%d, bssdes.ch_ID=%d, bssdes.rssi=%d, SpectCh.bssCount=%d, pScanResult=0x%x",
254 __FUNCTION__, pScanResult->BssDescriptor.channelIdSelf, pScanResult->BssDescriptor.channelId,
255 pScanResult->BssDescriptor.rssi, pSpectCh->bssCount, pScanResult);
256
257 pSpectCh++;
258 break;
259 } else {
260 pSpectCh++;
261 }
262 }
263
264 pScanResult = sme_ScanResultGetNext(halHandle, pResult);
265 }
266
267 // Calculate the weights for all channels in the spectrum pSpectCh
268 pSpectCh = pSpectInfoParams->pSpectCh;
269
270 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Spectrum Channels Weight", __FUNCTION__);
271
272 for (chn_num = 0; chn_num < (pSpectInfoParams->numSpectChans); chn_num++) {
273
274 /*
275 rssi : Maximum received signal strength among all BSS on that channel
276 bssCount : Number of BSS on that channel
277 */
278
279 rssi = (v_S7_t)pSpectCh->rssiAgr;
280
281 pSpectCh->weight = SAPDFS_NORMALISE_1000 * sapweightRssiCount(rssi, pSpectCh->bssCount);
282
283 //------ Debug Info ------
284 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Chan=%d Weight= %d rssiAgr=%d bssCount=%d", __FUNCTION__, pSpectCh->chNum,
285 pSpectCh->weight, pSpectCh->rssiAgr, pSpectCh->bssCount);
286 //------ Debug Info ------
287 pSpectCh++;
288 }
289}
290
291/*==========================================================================
292 FUNCTION sapChanSelExit
293
294 DESCRIPTION
295 Exit function for free out the allocated memory, to be called
296 at the end of the dfsSelectChannel function
297
298 DEPENDENCIES
299 NA.
300
301 PARAMETERS
302
303 IN
304 pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure
305
306 RETURN VALUE
307 void : NULL
308
309 SIDE EFFECTS
310============================================================================*/
311void sapChanSelExit( tSapChSelSpectInfo *pSpectInfoParams )
312{
313 // Free all the allocated memory
314 vos_mem_free(pSpectInfoParams->pSpectCh);
315}
316
317/*==========================================================================
318 FUNCTION sapSortChlWeight
319
320 DESCRIPTION
321 Funtion to sort the channels with the least weight first
322
323 DEPENDENCIES
324 NA.
325
326 PARAMETERS
327
328 IN
329 pSpectInfoParams : Pointer to the tSapChSelSpectInfo structure
330
331 RETURN VALUE
332 void : NULL
333
334 SIDE EFFECTS
335============================================================================*/
336void sapSortChlWeight(tSapChSelSpectInfo *pSpectInfoParams)
337{
338 tSapSpectChInfo temp;
339
340 tSapSpectChInfo *pSpectCh = NULL;
341 v_U32_t i = 0, j = 0, minWeightIndex = 0;
342
343 pSpectCh = pSpectInfoParams->pSpectCh;
344#ifdef SOFTAP_CHANNEL_RANGE
345 // Sorting the channels as per weights
346 for (i = 0; i < pSpectInfoParams->numSpectChans; i++) {
347 minWeightIndex = i;
348 for( j = i + 1; j < pSpectInfoParams->numSpectChans; j++) {
349 if(pSpectCh[j].weight < pSpectCh[minWeightIndex].weight) {
350 minWeightIndex = j;
351 }
352 }
353 if(minWeightIndex != i) {
354 vos_mem_copy(&temp, &pSpectCh[minWeightIndex], sizeof(*pSpectCh));
355 vos_mem_copy(&pSpectCh[minWeightIndex], &pSpectCh[i], sizeof(*pSpectCh));
356 vos_mem_copy(&pSpectCh[i], &temp, sizeof(*pSpectCh));
357 }
358 }
359#else
360 // Sorting the channels as per weights
361 for (i = 0; i < SPECT_24GHZ_CH_COUNT; i++) {
362 minWeightIndex = i;
363 for( j = i + 1; j < SPECT_24GHZ_CH_COUNT; j++) {
364 if(pSpectCh[j].weight < pSpectCh[minWeightIndex].weight) {
365 minWeightIndex = j;
366 }
367 }
368 if(minWeightIndex != i) {
369 vos_mem_copy(&temp, &pSpectCh[minWeightIndex], sizeof(*pSpectCh));
370 vos_mem_copy(&pSpectCh[minWeightIndex], &pSpectCh[i], sizeof(*pSpectCh));
371 vos_mem_copy(&pSpectCh[i], &temp, sizeof(*pSpectCh));
372 }
373 }
374#endif
375
376 /* For testing */
377 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Sorted Spectrum Channels Weight", __FUNCTION__);
378 pSpectCh = pSpectInfoParams->pSpectCh;
379 for (j = 0; j < (pSpectInfoParams->numSpectChans); j++) {
380 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Channel=%d Weight= %d rssi=%d bssCount=%d",
381 __FUNCTION__, pSpectCh->chNum, pSpectCh->weight, pSpectCh->rssiAgr, pSpectCh->bssCount);
382 pSpectCh++;
383 }
384
385}
386
387/*==========================================================================
388 FUNCTION sapSelectChannel
389
390 DESCRIPTION
391 Runs a algorithm to select the best channel to operate in based on BSS
392 rssi and bss count on each channel
393
394 DEPENDENCIES
395 NA.
396
397 PARAMETERS
398
399 IN
400 halHandle : Pointer to HAL handle
401 pResult : Pointer to tScanResultHandle
402
403 RETURN VALUE
404 v_U8_t : Success - channel number, Fail - zero
405
406 SIDE EFFECTS
407============================================================================*/
408v_U8_t sapSelectChannel(tHalHandle halHandle, tScanResultHandle pScanResult)
409{
410 // DFS param object holding all the data req by the algo
411 tSapChSelSpectInfo oSpectInfoParams = {NULL,0};
412 tSapChSelSpectInfo *pSpectInfoParams = &oSpectInfoParams; // Memory? NB
413
414 v_U8_t bestChNum = 0;
415#ifdef SOFTAP_CHANNEL_RANGE
416 v_U32_t startChannelNum;
417 v_U32_t endChannelNum;
418 v_U32_t operatingBand;
419 v_U8_t count = 0;
420#endif
421 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Running SAP Ch Select", __FUNCTION__);
422
423 // Set to zero tSapChSelParams
424 //vos_mem_zero(&sapChSelParams, sizeof(sapChSelParams));
425
426 // Initialize the structure pointed by pSpectInfoParams
427 if(sapChanSelInit( halHandle, pSpectInfoParams) != eSAP_TRUE ) {
428 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "In %s, Ch Select initialization failed", __FUNCTION__);
429 return SAP_CHANNEL_NOT_SELECTED;
430 }
431
432 // Compute the weight of the entire spectrum in the operating band
433 sapComputeSpectWeight( pSpectInfoParams, halHandle, pScanResult);
434
435 // Sort the 20M channel list as per the computed weights, lesser weight first.
436 sapSortChlWeight(pSpectInfoParams);
437
438#ifdef SOFTAP_CHANNEL_RANGE
439 ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL, &startChannelNum);
440 ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL, &endChannelNum);
441 ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND, &operatingBand);
442
443 /*Loop till get the best channel in the given range */
444 for(count=0; count < pSpectInfoParams->numSpectChans ; count++)
445 {
446 if((startChannelNum <= pSpectInfoParams->pSpectCh[count].chNum)&&
447 ( endChannelNum >= pSpectInfoParams->pSpectCh[count].chNum))
448 {
449 bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum;
450 break;
451 }
452 }
453
454#else
455 // Get the first channel in sorted array as best 20M Channel
456 bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[0].chNum;
457
458#endif
459
460 // Free all the allocated memory
461 sapChanSelExit(pSpectInfoParams);
462
463 VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Running SAP Ch select Completed, Ch=%d",
464 __FUNCTION__, bestChNum);
465
466 if (bestChNum > 0 && bestChNum <= 252)
467 return bestChNum;
468 else
469 return SAP_CHANNEL_NOT_SELECTED;
470}
471