blob: 7d18bb66e1a520ffc09cfbbbb82d73c141a902a0 [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/**=========================================================================
25
26 \file sme_Rrm.c
27
28 \brief implementation for SME RRM APIs
29
30 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
31
32 Qualcomm Confidential and Proprietary.
33
34 ========================================================================*/
35
36/* $Header$ */
37
38#if defined WLAN_FEATURE_VOWIFI
39/*--------------------------------------------------------------------------
40 Include Files
41 ------------------------------------------------------------------------*/
42#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
43#include "halInternal.h"
44#endif
45#include "aniGlobal.h"
46#include "smeInside.h"
47#include "sme_Api.h"
48#include "smsDebug.h"
49#include "cfgApi.h"
50
51#ifdef FEATURE_WLAN_DIAG_SUPPORT
52#include "vos_diag_core_event.h"
53#include "vos_diag_core_log.h"
54#endif /* FEATURE_WLAN_DIAG_SUPPORT */
55
56#include "csrInsideApi.h"
57
58#include "rrmGlobal.h"
59
60#ifdef FEATURE_WLAN_CCX
61#include "csrCcx.h"
62#endif
63
64/* Roam score for a neighbor AP will be calculated based on the below definitions.
65 The calculated roam score will be used to select the roamable candidate from neighbor AP list */
66#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY 0 /* When we support 11r over the DS, this should have a non-zero value */
67#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY 10
68#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE 20
69#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT 0 /* Not used */
70#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS 5
71#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD 3
72#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM 8
73#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA 0 /* We dont support delayed BA */
74#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA 3
75#define RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN 30
76
77#ifdef FEATURE_WLAN_CCX
78#define RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST 30
79#endif
80/**---------------------------------------------------------------------------
81
82 \brief rrmLLPurgeNeighborCache() -
83 This function purges all the entries in the neighbor cache and frees up all the internal nodes
84
85 \param - pMac - Pointer to the Hal Handle.
86 - pList - Pointer the List that should be purged.
87 \return - void
88
89 --------------------------------------------------------------------------*/
90static void rrmLLPurgeNeighborCache(tpAniSirGlobal pMac, tDblLinkList *pList)
91{
92 tListElem *pEntry;
93 tRrmNeighborReportDesc *pNeighborReportDesc;
94
95 csrLLLock(pList);
96
97 while((pEntry = csrLLRemoveHead(pList, LL_ACCESS_NOLOCK)) != NULL)
98 {
99 pNeighborReportDesc = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List );
100 vos_mem_free(pNeighborReportDesc->pNeighborBssDescription);
101 vos_mem_free(pNeighborReportDesc);
102 }
103
104 csrLLUnlock(pList);
105
106 return;
107}
108
109/**---------------------------------------------------------------------------
110
111 \brief rrmIndicateNeighborReportResult() -
112 This function calls the callback register by the caller while requesting for
113 neighbor report. This function gets invoked if a neighbor report is received from an AP
114 or neighbor response wait timer expires.
115
116 \param - pMac - Pointer to the Hal Handle.
117 - vosStatus - VOS_STATUS_SUCCESS/VOS_STATUS_FAILURE based on whether a valid report is
118 received or neighbor timer expired
119 \return - void
120
121 --------------------------------------------------------------------------*/
122void rrmIndicateNeighborReportResult(tpAniSirGlobal pMac, VOS_STATUS vosStatus)
123{
124 NeighborReportRspCallback callback;
125 void *callbackContext;
126
127 /* Reset the neighbor response pending status */
128 pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = eANI_BOOLEAN_FALSE;
129
130 /* Stop the timer if it is already running. The timer should be running only in the SUCCESS case. */
131 if (VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer))
132 {
133 VOS_ASSERT(VOS_STATUS_SUCCESS == vosStatus);
134 vos_timer_stop(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer);
135 }
136 callback = pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback;
137 callbackContext = pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallbackContext;
138
139 /* Reset the callback and the callback context before calling the callback. It is very likely that there may be a registration in
140 callback itself. */
141 pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback = NULL;
142 pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallbackContext = NULL;
143
144 /* Call the callback with the status received from caller */
145 if (callback)
146 callback(callbackContext, vosStatus);
147#ifdef FEATURE_WLAN_CCX
148 // We came here with IAPP AP List
149 // Make sure we inform CSR of the neighbor list
150 // for CCX Associations. First clear the cache.
151 else
152 if (csrNeighborRoamIsCCXAssoc(pMac))
153 {
154 ProcessIAPPNeighborAPList(pMac);
155 }
156#endif
157
158 return;
159
160}
161
162/**---------------------------------------------------------------------------
163
164 \brief sme_RrmBeaconReportXmitInd() -
165
166 Create and send the beacon report Xmit ind message to PE.
167
168 \param - pMac - Pointer to the Hal Handle.
169 - pResult - scan result.
170 - measurementDone - flag to indicate that the measurement is done.
171 \return - 0 for success, non zero for failure
172
173 --------------------------------------------------------------------------*/
174static eHalStatus sme_RrmSendBeaconReportXmitInd( tpAniSirGlobal pMac, tCsrScanResultInfo **pResultArr, tANI_U8 measurementDone )
175{
176 tpSirBssDescription pBssDesc = NULL;
177 tpSirBeaconReportXmitInd pBeaconRep;
178 tANI_U16 length, ie_len;
179 tANI_U8 bssCounter=0, msgCounter=0;
180 tCsrScanResultInfo *pCurResult=NULL;
181 eHalStatus status = eHAL_STATUS_FAILURE;
182 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
183
184
185#if defined WLAN_VOWIFI_DEBUG
186 smsLog( pMac, LOGE, "Beacon report xmit Ind to PE\n");
187#endif
188
189 if( NULL == pResultArr && !measurementDone )
190 {
191 smsLog( pMac, LOGE, "Beacon report xmit Ind to PE Failed\n");
192 return eHAL_STATUS_FAILURE;
193 }
194
195 if (pResultArr)
196 pCurResult=pResultArr[bssCounter];
197
198 do
199 {
200 length = sizeof(tSirBeaconReportXmitInd);
201 pBeaconRep = vos_mem_malloc ( length );
202 if ( NULL == pBeaconRep )
203 {
204 smsLog( pMac, LOGP, "Unable to allocate memory for beacon report");
205 return eHAL_STATUS_FAILED_ALLOC;
206 }
207 vos_mem_zero( pBeaconRep, length );
208#if defined WLAN_VOWIFI_DEBUG
209 smsLog( pMac, LOGE, FL("Allocated memory for pBeaconRep\n"));
210#endif
211 pBeaconRep->messageType = eWNI_SME_BEACON_REPORT_RESP_XMIT_IND;
212 pBeaconRep->length = length;
213 pBeaconRep->uDialogToken = pSmeRrmContext->token;
214 pBeaconRep->duration = pSmeRrmContext->duration;
215 pBeaconRep->regClass = pSmeRrmContext->regClass;
216 vos_mem_copy( pBeaconRep->bssId, pSmeRrmContext->sessionBssId, sizeof(tSirMacAddr) );
217
218 msgCounter=0;
219 while (pCurResult)
220 {
221 pBssDesc = &pCurResult->BssDescriptor;
222 ie_len = GET_IE_LEN_IN_BSS( pBssDesc->length );
223 pBeaconRep->pBssDescription[msgCounter] = vos_mem_malloc ( ie_len+sizeof(tSirBssDescription) );
224 vos_mem_copy( pBeaconRep->pBssDescription[msgCounter], pBssDesc, sizeof(tSirBssDescription) );
225 vos_mem_copy( &pBeaconRep->pBssDescription[msgCounter]->ieFields[0], pBssDesc->ieFields, ie_len );
226
227 pBeaconRep->numBssDesc++;
228
229 if (++msgCounter >= SIR_BCN_REPORT_MAX_BSS_DESC)
230 break;
231
232 if (csrRoamIs11rAssoc(pMac)) {
233 break;
234 }
235
236 pCurResult = pResultArr[msgCounter];
237 }
238
239 bssCounter+=msgCounter;
240 if (!pResultArr || !pCurResult || (bssCounter>=SIR_BCN_REPORT_MAX_BSS_DESC))
241 pCurResult = NULL;
242 else
243 pCurResult = pResultArr[bssCounter];
244
245 pBeaconRep->fMeasureDone = (pCurResult)?false:measurementDone;
246
247 status = palSendMBMessage(pMac->hHdd, pBeaconRep);
248
249 smsLog( pMac, LOGW, "SME Sent BcnRepXmit to PE numBss %d\n", pBeaconRep->numBssDesc);
250
251 } while (pCurResult);
252
253 return status;
254}
255
256/**---------------------------------------------------------------------------
257
258 \brief sme_RrmSendScanRequest() -
259
260 This function is called to get the scan result from CSR and send the beacon report
261 xmit ind message to PE.
262
263 \param - pMac - Pointer to the Hal Handle.
264 - num_chan - number of channels.
265 - channel list - list of channels to fetch the result from.
266 - measurementDone - flag to indicate that the measurement is done.
267 \return - 0 for success, non zero for failure
268
269 --------------------------------------------------------------------------*/
270static eHalStatus sme_RrmSendScanResult( tpAniSirGlobal pMac, tANI_U8 num_chan, tANI_U8* chanList, tANI_U8 measurementDone )
271{
272 tCsrScanResultFilter filter;
273 tScanResultHandle pResult;
274 tCsrScanResultInfo *pScanResult, *pNextResult;
275 tCsrScanResultInfo *pScanResultsArr[SIR_BCN_REPORT_MAX_BSS_DESC];
276 eHalStatus status;
277 tANI_U8 counter=0;
278 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
279 tANI_U32 sessionId;
280
281#if defined WLAN_VOWIFI_DEBUG
282 smsLog( pMac, LOGE, "Send scan result to PE \n");
283#endif
284
285 vos_mem_zero( &filter, sizeof(filter) );
286 vos_mem_zero( pScanResultsArr, sizeof(pNextResult)*SIR_BCN_REPORT_MAX_BSS_DESC );
287
288 filter.BSSIDs.numOfBSSIDs = 1;
289 filter.BSSIDs.bssid = &pSmeRrmContext->bssId;
290
291 if( pSmeRrmContext->ssId.length )
292 {
293 filter.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
294 if( filter.SSIDs.SSIDList == NULL )
295 {
296 smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") );
297 return eHAL_STATUS_FAILURE;
298 }
299#if defined WLAN_VOWIFI_DEBUG
300 smsLog( pMac, LOGE, FL("Allocated memory for SSIDList\n"));
301#endif
302 vos_mem_zero( filter.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) );
303
304 filter.SSIDs.SSIDList->SSID.length = pSmeRrmContext->ssId.length;
305 vos_mem_copy(filter.SSIDs.SSIDList->SSID.ssId, pSmeRrmContext->ssId.ssId, pSmeRrmContext->ssId.length);
306 filter.SSIDs.numOfSSIDs = 1;
307 }
308 else
309 {
310 filter.SSIDs.numOfSSIDs = 0;
311 }
312
313 filter.ChannelInfo.numOfChannels = num_chan;
314 filter.ChannelInfo.ChannelList = chanList;
315
316 filter.fMeasurement = TRUE;
317
318 csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid*)pSmeRrmContext->sessionBssId, &sessionId );
319 status = sme_ScanGetResult(pMac, (tANI_U8)sessionId, &filter, &pResult);
320
321 if( filter.SSIDs.SSIDList )
322 {
323 //Free the memory allocated for SSIDList.
324 vos_mem_free( filter.SSIDs.SSIDList );
325#if defined WLAN_VOWIFI_DEBUG
326 smsLog( pMac, LOGE, FL("Free memory for SSIDList\n") );
327#endif
328 }
329
330 if (NULL == pResult)
331 {
332 // no scan results
333 //
334 // Spec. doesnt say anything about such condition.
335 // Since section 7.4.6.2 (IEEE802.11k-2008) says-rrm report frame should contain
336 // one or more report IEs. It probably means dont send any respose if no matching
337 // BSS found. Moreover, there is no flag or field in measurement report IE(7.3.2.22)
338 // OR beacon report IE(7.3.2.22.6) that can be set to indicate no BSS found on a given channel.
339 //
340 // If we finished measurement on all the channels, we still need to
341 // send a xmit indication with moreToFollow set to MEASURMENT_DONE
342 // so that PE can clean any context allocated.
343 if( measurementDone )
344 status = sme_RrmSendBeaconReportXmitInd( pMac, NULL, measurementDone );
345 return status;
346 }
347
348 pScanResult = sme_ScanResultGetFirst(pMac, pResult);
349
350 if( NULL == pScanResult && measurementDone )
351 status = sme_RrmSendBeaconReportXmitInd( pMac, NULL, measurementDone );
352
353 counter=0;
354 while (pScanResult)
355 {
356 pNextResult = sme_ScanResultGetNext(pMac, pResult);
357 pScanResultsArr[counter++] = pScanResult;
358 pScanResult = pNextResult; //sme_ScanResultGetNext(hHal, pResult);
359 if (counter >= SIR_BCN_REPORT_MAX_BSS_DESC)
360 break;
361 }
362
363 if (counter)
364 status = sme_RrmSendBeaconReportXmitInd( pMac, pScanResultsArr, measurementDone);
365
366 sme_ScanResultPurge(pMac, pResult);
367
368 return status;
369}
370/**---------------------------------------------------------------------------
371
372 \brief sme_RrmScanRequestCallback() -
373
374 The sme module calls this callback function once it finish the scan request
375 and this function send the beacon report xmit to PE and starts a timer of
376 random interval to issue next request.
377
378 \param - halHandle - Pointer to the Hal Handle.
379 - pContext - Pointer to the data context.
380 - scanId - Scan ID.
381 - status - CSR Status.
382 \return - 0 for success, non zero for failure
383
384 --------------------------------------------------------------------------*/
385
386static eHalStatus sme_RrmScanRequestCallback(tHalHandle halHandle, void *pContext,
387 tANI_U32 scanId, eCsrScanStatus status)
388{
389
390 tANI_U16 interval;
391 tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle;
392 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
393 tANI_U32 time_tick;
394
395
396
397#if defined WLAN_VOWIFI_DEBUG
398 smsLog( pMac, LOGE, "Scan Request callback \n");
399#endif
400 //if any more channels are pending, start a timer of a random value within randomization interval.
401 //
402 //
403 if( (pSmeRrmContext->currentIndex + 1) < pSmeRrmContext->channelList.numOfChannels )
404 {
405 sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], false );
406
407 pSmeRrmContext->currentIndex++; //Advance the current index.
408 //start the timer to issue next request.
409 //From timer tick get a random number within 10ms and max randmization interval.
410 time_tick = vos_timer_get_system_ticks();
411 interval = time_tick % (pSmeRrmContext->randnIntvl - 10 + 1) + 10;
412
413#if defined WLAN_VOWIFI_DEBUG
414 smsLog( pMac, LOGE, "Set timer for interval %d \n", interval);
415#endif
416 vos_timer_start( &pSmeRrmContext->IterMeasTimer, interval );
417
418 }
419 else
420 {
421 //Done with the measurement. Clean up all context and send a message to PE with measurement done flag set.
422 sme_RrmSendScanResult( pMac, 1, &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex], true );
423 vos_mem_free( pSmeRrmContext->channelList.ChannelList );
424#if defined WLAN_VOWIFI_DEBUG
425 smsLog( pMac, LOGE, FL("Free memory for ChannelList\n") );
426#endif
427 }
428
429 return eHAL_STATUS_SUCCESS;
430}
431
432/*--------------------------------------------------------------------------
433 \brief sme_RrmIssueScanReq() - This is called to send a scan request as part
434 of beacon report request .
435
436 \param
437
438 \return eHAL_STATUS_SUCCESS - Validation is successful.
439
440 \sa
441
442 --------------------------------------------------------------------------*/
443eHalStatus sme_RrmIssueScanReq( tpAniSirGlobal pMac )
444{
445 //Issue scan request.
446 tCsrScanRequest scanRequest;
447 v_U32_t scanId = 0;
448 eHalStatus status = eHAL_STATUS_SUCCESS;
449 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
450 tANI_U32 sessionId;
451
452#if defined WLAN_VOWIFI_DEBUG
453 smsLog( pMac, LOGE, "Issue scan request \n" );
454#endif
455
456 vos_mem_zero( &scanRequest, sizeof(scanRequest));
457
458 /* set scanType, active or passive */
459
460 scanRequest.scanType = pSmeRrmContext->measMode;
461
462 vos_mem_copy(scanRequest.bssid,
463 pSmeRrmContext->bssId, sizeof(scanRequest.bssid) );
464
465 if( pSmeRrmContext->ssId.length )
466 {
467 scanRequest.SSIDs.numOfSSIDs = 1;
468 scanRequest.SSIDs.SSIDList =( tCsrSSIDInfo *)vos_mem_malloc(sizeof(tCsrSSIDInfo));
469 if( scanRequest.SSIDs.SSIDList == NULL )
470 {
471 smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") );
472 return eHAL_STATUS_FAILURE;
473 }
474#if defined WLAN_VOWIFI_DEBUG
475 smsLog( pMac, LOGE, FL("Allocated memory for pSSIDList\n"));
476#endif
477 vos_mem_zero( scanRequest.SSIDs.SSIDList, sizeof(tCsrSSIDInfo) );
478 scanRequest.SSIDs.SSIDList->SSID.length = pSmeRrmContext->ssId.length;
479 vos_mem_copy(scanRequest.SSIDs.SSIDList->SSID.ssId, pSmeRrmContext->ssId.ssId, pSmeRrmContext->ssId.length);
480 }
481
482 /* set min and max channel time */
483 scanRequest.minChnTime = 0; //pSmeRrmContext->duration; Dont use min timeout.
484 scanRequest.maxChnTime = pSmeRrmContext->duration;
485#if defined WLAN_VOWIFI_DEBUG
486 smsLog( pMac, LOGE, "For Duration %d \n", pSmeRrmContext->duration );
487#endif
488
489 /* set BSSType to default type */
490 scanRequest.BSSType = eCSR_BSS_TYPE_ANY;
491
492 /*Scan all the channels */
493 scanRequest.ChannelInfo.numOfChannels = 1;
494
495 scanRequest.ChannelInfo.ChannelList = &pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex];
496#if defined WLAN_VOWIFI_DEBUG
497 smsLog( pMac, LOGE, "On channel %d \n", pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->currentIndex] );
498#endif
499
500 /* set requestType to full scan */
501 scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
502
503 csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid*)pSmeRrmContext->sessionBssId, &sessionId );
504 status = sme_ScanRequest( pMac, (tANI_U8)sessionId, &scanRequest, &scanId, &sme_RrmScanRequestCallback, NULL );
505
506 if ( pSmeRrmContext->ssId.length )
507 {
508 vos_mem_free(scanRequest.SSIDs.SSIDList);
509#if defined WLAN_VOWIFI_DEBUG
510 smsLog( pMac, LOGE, FL("Free memory for SSIDList\n"));
511#endif
512 }
513
514 return status;
515}
516
517/*--------------------------------------------------------------------------
518 \brief sme_RrmProcessBeaconReportReqInd() - This is called to process the Beacon
519 report request from peer AP forwarded through PE .
520
521 \param pMsgBuf - a pointer to a buffer that maps to various structures base
522 on the message type.
523 The beginning of the buffer can always map to tSirSmeRsp.
524
525 \return eHAL_STATUS_SUCCESS - Validation is successful.
526
527 \sa
528
529 --------------------------------------------------------------------------*/
530void sme_RrmProcessBeaconReportReqInd(tpAniSirGlobal pMac, void *pMsgBuf)
531{
532 tpSirBeaconReportReqInd pBeaconReq = (tpSirBeaconReportReqInd) pMsgBuf;
533 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
534 tANI_U32 len,i;
535
536#if defined WLAN_VOWIFI_DEBUG
537 smsLog( pMac, LOGE, "Received Beacon report request ind Channel = %d\n", pBeaconReq->channelInfo.channelNum );
538#endif
539 //section 11.10.8.1 (IEEE Std 802.11k-2008)
540 //channel 0 and 255 has special meaning.
541 if( (pBeaconReq->channelInfo.channelNum == 0) ||
542 ((pBeaconReq->channelInfo.channelNum == 255) && (pBeaconReq->channelList.numChannels == 0) ) )
543 {
544 //Add all the channel in the regulatory domain.
545 wlan_cfgGetStrLen( pMac, WNI_CFG_VALID_CHANNEL_LIST, &len );
546 pSmeRrmContext->channelList.ChannelList = vos_mem_malloc( len );
547 if( pSmeRrmContext->channelList.ChannelList == NULL )
548 {
549 smsLog( pMac, LOGP, FL("vos_mem_malloc failed:") );
550 return;
551 }
552#if defined WLAN_VOWIFI_DEBUG
553 smsLog( pMac, LOGE, FL("Allocated memory for ChannelList\n") );
554#endif
555 csrGetCfgValidChannels( pMac, pSmeRrmContext->channelList.ChannelList, &len );
556 pSmeRrmContext->channelList.numOfChannels = (tANI_U8)len;
557#if defined WLAN_VOWIFI_DEBUG
558 smsLog( pMac, LOGE, "channel == 0 perfoming on all channels \n");
559#endif
560 }
561 else
562 {
563 len = 0;
564 pSmeRrmContext->channelList.numOfChannels = 0;
565
566 //If valid channel is present. We firt Measure on the given channel. and
567 //if there are additional channels present in APchannelreport, measure on these also.
568 if ( pBeaconReq->channelInfo.channelNum != 255 )
569 len = 1;
570#if defined WLAN_VOWIFI_DEBUG
571 else
572 smsLog( pMac, LOGE, "channel == 255 \n");
573#endif
574
575 len += pBeaconReq->channelList.numChannels;
576
577 pSmeRrmContext->channelList.ChannelList = vos_mem_malloc( len );
578 if( pSmeRrmContext->channelList.ChannelList == NULL )
579 {
580 smsLog( pMac, LOGP, FL("vos_mem_malloc failed") );
581 return;
582 }
583#if defined WLAN_VOWIFI_DEBUG
584 smsLog( pMac, LOGE, FL("Allocated memory for ChannelList\n") );
585#endif
586
587 if ( pBeaconReq->channelInfo.channelNum != 255 )
588 {
589#if defined WLAN_VOWIFI_DEBUG
590 smsLog( pMac, LOGE, "channel == %d \n", pBeaconReq->channelInfo.channelNum );
591#endif
592 if(csrRoamIsChannelValid( pMac, pBeaconReq->channelInfo.channelNum ))
593 pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->channelList.numOfChannels++] = pBeaconReq->channelInfo.channelNum;
594#if defined WLAN_VOWIFI_DEBUG
595 else
596 smsLog( pMac, LOGE, "is Invalid channel, Ignoring this channel\n" );
597#endif
598 }
599
600 for ( i = 0 ; i < pBeaconReq->channelList.numChannels; i++ )
601 {
602 if(csrRoamIsChannelValid( pMac, pBeaconReq->channelList.channelNumber[i] ))
603 {
604 pSmeRrmContext->channelList.ChannelList[pSmeRrmContext->channelList.numOfChannels] = pBeaconReq->channelList.channelNumber[i];
605 pSmeRrmContext->channelList.numOfChannels++;
606 }
607 }
608 }
609
610 //Copy session bssid
611 vos_mem_copy( pSmeRrmContext->sessionBssId, pBeaconReq->bssId, sizeof(tSirMacAddr) );
612
613 //copy measurement bssid
614 vos_mem_copy( pSmeRrmContext->bssId, pBeaconReq->macaddrBssid, sizeof(tSirMacAddr) );
615
616 //Copy ssid
617 vos_mem_copy( &pSmeRrmContext->ssId, &pBeaconReq->ssId, sizeof(tAniSSID) );
618
619 pSmeRrmContext->token = pBeaconReq->uDialogToken;
620 pSmeRrmContext->regClass = pBeaconReq->channelInfo.regulatoryClass;
621
622 switch( pBeaconReq->fMeasurementtype )
623 {
624 case 0: //Passive
625 case 1: //Active
626 pSmeRrmContext->measMode = pBeaconReq->fMeasurementtype? eSIR_ACTIVE_SCAN : eSIR_PASSIVE_SCAN ;
627 pSmeRrmContext->duration = pBeaconReq->measurementDuration;
628 pSmeRrmContext->randnIntvl = VOS_MAX( pBeaconReq->randomizationInterval, pSmeRrmContext->rrmConfig.maxRandnInterval );
629 pSmeRrmContext->currentIndex = 0;
630#if defined WLAN_VOWIFI_DEBUG
631 smsLog( pMac, LOGE, "Send beacon report after scan \n" );
632#endif
633 sme_RrmIssueScanReq( pMac );
634 break;
635 case 2: //Table
636 //Get the current scan results for the given channel and send it.
637#if defined WLAN_VOWIFI_DEBUG
638 smsLog( pMac, LOGE, "Send beacon report from table \n" );
639#endif
640 sme_RrmSendScanResult( pMac, pSmeRrmContext->channelList.numOfChannels, pSmeRrmContext->channelList.ChannelList, true );
641 vos_mem_free( pSmeRrmContext->channelList.ChannelList );
642#if defined WLAN_VOWIFI_DEBUG
643 smsLog( pMac, LOGE, FL("Free memory for ChannelList\n") );
644#endif
645 break;
646 default:
647#if defined WLAN_VOWIFI_DEBUG
648 smsLog( pMac, LOGE, "Unknown beacon report request mode\n");
649#endif
650 /* Indicate measurement completion to PE */
651 /* If this is not done, pCurrentReq pointer will not be freed and
652 PE will not handle subsequent Beacon requests */
653 sme_RrmSendBeaconReportXmitInd(pMac, NULL, true);
654 break;
655
656 }
657
658 return;
659}
660
661/*--------------------------------------------------------------------------
662 \brief sme_RrmNeighborReportRequest() - This is API can be used to trigger a
663 Neighbor report from the peer.
664
665 \param sessionId - session identifier on which the request should be made.
666 \param pNeighborReq - a pointer to a neighbor report request.
667
668 \return eHAL_STATUS_SUCCESS - Validation is successful.
669
670 \sa
671
672 --------------------------------------------------------------------------*/
673VOS_STATUS sme_RrmNeighborReportRequest(tpAniSirGlobal pMac, tANI_U8 sessionId,
674 tpRrmNeighborReq pNeighborReq, tpRrmNeighborRspCallbackInfo callbackInfo)
675{
676 eHalStatus status = eHAL_STATUS_SUCCESS;
677 tpSirNeighborReportReqInd pMsg;
678 tCsrRoamSession *pSession;
679
680#if defined WLAN_VOWIFI_DEBUG
681 smsLog( pMac, LOGE, FL("Request to send Neighbor report request received \n"));
682#endif
683 if( !CSR_IS_SESSION_VALID( pMac, sessionId ) )
684 {
685 smsLog( pMac, LOGE, FL("Invalid session %d\n"), sessionId );
686 return VOS_STATUS_E_INVAL;
687 }
688 pSession = CSR_GET_SESSION( pMac, sessionId );
689
690 /* If already a report is pending, return failure */
691 if (eANI_BOOLEAN_TRUE == pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending)
692 {
693 smsLog( pMac, LOGE, FL("Neighbor request already pending.. Not allowed"));
694 return VOS_STATUS_E_AGAIN;
695 }
696
697 pMsg = vos_mem_malloc ( sizeof(tSirNeighborReportReqInd) );
698 if ( NULL == pMsg )
699 {
700 smsLog( pMac, LOGE, "Unable to allocate memory for Neighbor request");
701 return VOS_STATUS_E_NOMEM;
702 }
703
704
705 vos_mem_zero( pMsg, sizeof(tSirNeighborReportReqInd) );
706#if defined WLAN_VOWIFI_DEBUG
707 smsLog( pMac, LOGE, FL(" Allocated memory for Neighbor request\n") );
708#endif
709
710 rrmLLPurgeNeighborCache(pMac, &pMac->rrm.rrmSmeContext.neighborReportCache);
711
712#if defined WLAN_VOWIFI_DEBUG
713 smsLog( pMac, LOGE, FL("Purged the neighbor cache before sending Neighbor request: Status = %d\n"), status );
714#endif
715
716 pMsg->messageType = eWNI_SME_NEIGHBOR_REPORT_REQ_IND;
717 pMsg->length = sizeof( tSirNeighborReportReqInd );
718 vos_mem_copy( &pMsg->bssId, &pSession->connectedProfile.bssid, sizeof(tSirMacAddr) );
719 pMsg->noSSID = pNeighborReq->no_ssid;
720 vos_mem_copy( &pMsg->ucSSID, &pNeighborReq->ssid, sizeof(tSirMacSSid));
721
722 status = palSendMBMessage(pMac->hHdd, pMsg);
723 if( status != eHAL_STATUS_SUCCESS )
724 return VOS_STATUS_E_FAILURE;
725
726 /* Neighbor report request message sent successfully to PE. Now register the callbacks */
727 pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback =
728 callbackInfo->neighborRspCallback;
729 pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallbackContext =
730 callbackInfo->neighborRspCallbackContext;
731 pMac->rrm.rrmSmeContext.neighborReqControlInfo.isNeighborRspPending = eANI_BOOLEAN_TRUE;
732
733 /* Start neighbor response wait timer now */
734 vos_timer_start(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer, callbackInfo->timeout);
735
736 return VOS_STATUS_SUCCESS;
737}
738
739/*--------------------------------------------------------------------------
740 \brief rrmCalculateNeighborAPRoamScore() - This API is called while handling
741 individual neighbor reports from the APs neighbor AP report to
742 calculate the cumulative roam score before storing it in neighbor
743 cache.
744
745 \param pNeighborReportDesc - Neighbor BSS Descriptor node for which roam score
746 should be calculated
747
748 \return void.
749--------------------------------------------------------------------------*/
750static void rrmCalculateNeighborAPRoamScore(tpAniSirGlobal pMac, tpRrmNeighborReportDesc pNeighborReportDesc)
751{
752 tpSirNeighborBssDescripton pNeighborBssDesc;
753 tANI_U32 roamScore = 0;
754
755 VOS_ASSERT(pNeighborReportDesc != NULL);
756 VOS_ASSERT(pNeighborReportDesc->pNeighborBssDescription != NULL);
757
758 pNeighborBssDesc = pNeighborReportDesc->pNeighborBssDescription;
759
760 if (pNeighborBssDesc->bssidInfo.rrmInfo.fMobilityDomain)
761 {
762 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_MOBILITY_DOMAIN;
763 if (pNeighborBssDesc->bssidInfo.rrmInfo.fSameSecurityMode)
764 {
765 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_SECURITY;
766 if (pNeighborBssDesc->bssidInfo.rrmInfo.fSameAuthenticator)
767 {
768 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_KEY_SCOPE;
769 if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapRadioMeasurement)
770 {
771 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_RRM;
772 if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapSpectrumMeasurement)
773 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_SPECTRUM_MGMT;
774 if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapQos)
775 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_QOS;
776 if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapApsd)
777 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_APSD;
778 if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapDelayedBlockAck)
779 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_DELAYED_BA;
780 if (pNeighborBssDesc->bssidInfo.rrmInfo.fCapImmediateBlockAck)
781 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_CAPABILITY_IMMEDIATE_BA;
782 if (pNeighborBssDesc->bssidInfo.rrmInfo.fApPreauthReachable)
783 roamScore += RRM_ROAM_SCORE_NEIGHBOR_REPORT_REACHABILITY;
784 }
785 }
786 }
787 }
788#ifdef FEATURE_WLAN_CCX
789 // It has come in the report so its the best score
790 if (csrNeighborRoamIs11rAssoc(pMac) == FALSE)
791 {
792 // IAPP Route so lets make use of this info
793 // save all AP, as the list does not come all the time
794 // Save and reuse till the next AP List comes to us.
795 // Even save our own MAC address. Will be useful next time around.
796 roamScore += RRM_ROAM_SCORE_NEIGHBOR_IAPP_LIST;
797 }
798#endif
799 pNeighborReportDesc->roamScore = roamScore;
800
801 return;
802}
803
804/*--------------------------------------------------------------------------
805 \brief rrmStoreNeighborRptByRoamScore() - This API is called to store a given
806 Neighbor BSS descriptor to the neighbor cache. This function
807 stores the neighbor BSS descriptors in such a way that descriptors
808 are sorted by roamScore in descending order
809
810 \param pNeighborReportDesc - Neighbor BSS Descriptor node to be stored in cache
811
812 \return void.
813--------------------------------------------------------------------------*/
814void rrmStoreNeighborRptByRoamScore(tpAniSirGlobal pMac, tpRrmNeighborReportDesc pNeighborReportDesc)
815{
816 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
817 tListElem *pEntry;
818 tRrmNeighborReportDesc *pTempNeighborReportDesc;
819
820 VOS_ASSERT(pNeighborReportDesc != NULL);
821 VOS_ASSERT(pNeighborReportDesc->pNeighborBssDescription != NULL);
822
823 if (csrLLIsListEmpty(&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK))
824 {
825 smsLog(pMac, LOGE, FL("Neighbor report cache is empty.. Adding a entry now\n"));
826 /* Neighbor list cache is empty. Insert this entry in the tail */
827 csrLLInsertTail(&pSmeRrmContext->neighborReportCache, &pNeighborReportDesc->List, LL_ACCESS_LOCK);
828 return;
829 }
830 else
831 {
832 /* Should store the neighbor BSS description in the order sorted by roamScore in descending
833 order. APs with highest roamScore should be the 1st entry in the list */
834 pEntry = csrLLPeekHead(&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK);
835 while (pEntry != NULL)
836 {
837 pTempNeighborReportDesc = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List );
838 if (pTempNeighborReportDesc->roamScore < pNeighborReportDesc->roamScore)
839 break;
840 pEntry = csrLLNext(&pSmeRrmContext->neighborReportCache, pEntry, LL_ACCESS_LOCK);
841 }
842
843 if (pEntry)
844 /* This BSS roamscore is better than something in the list. Insert this before that one */
845 csrLLInsertEntry(&pSmeRrmContext->neighborReportCache, pEntry, &pNeighborReportDesc->List, LL_ACCESS_LOCK);
846 else
847 /* All the entries in the list has a better roam Score than this one. Insert this at the last */
848 csrLLInsertTail(&pSmeRrmContext->neighborReportCache, &pNeighborReportDesc->List, LL_ACCESS_LOCK);
849 }
850 return;
851}
852
853/*--------------------------------------------------------------------------
854 \brief sme_RrmProcessNeighborReport() - This is called to process the Neighbor
855 report received from PE.
856
857 \param pMsgBuf - a pointer to a buffer that maps to various structures base
858 on the message type.
859 The beginning of the buffer can always map to tSirSmeRsp.
860
861 \return eHAL_STATUS_SUCCESS - Validation is successful.
862
863 \sa
864
865 --------------------------------------------------------------------------*/
866eHalStatus sme_RrmProcessNeighborReport(tpAniSirGlobal pMac, void *pMsgBuf)
867{
868 eHalStatus status = eHAL_STATUS_SUCCESS;
869 tpSirNeighborReportInd pNeighborRpt = (tpSirNeighborReportInd) pMsgBuf;
870 tpRrmNeighborReportDesc pNeighborReportDesc;
871 tANI_U8 i = 0;
872 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
873
874#ifdef FEATURE_WLAN_CCX
875 // Clear the cache for CCX.
876 if (csrNeighborRoamIsCCXAssoc(pMac))
877 {
878 rrmLLPurgeNeighborCache(pMac,
879 &pMac->rrm.rrmSmeContext.neighborReportCache);
880 }
881#endif
882
883 for (i = 0; i < pNeighborRpt->numNeighborReports; i++)
884 {
885 pNeighborReportDesc = vos_mem_malloc(sizeof(tRrmNeighborReportDesc));
886 if (NULL == pNeighborReportDesc)
887 {
888 smsLog( pMac, LOGE, "Failed to allocate memory for RRM Neighbor report desc\n");
889 status = eHAL_STATUS_FAILED_ALLOC;
890 goto end;
891
892 }
893
894 vos_mem_zero(pNeighborReportDesc, sizeof(tRrmNeighborReportDesc));
895 pNeighborReportDesc->pNeighborBssDescription = vos_mem_malloc(sizeof(tSirNeighborBssDescription));
896 if (NULL == pNeighborReportDesc->pNeighborBssDescription)
897 {
898 smsLog( pMac, LOGE, "Failed to allocate memory for RRM Neighbor report BSS Description\n");
899 status = eHAL_STATUS_FAILED_ALLOC;
900 goto end;
901 }
902 vos_mem_zero(pNeighborReportDesc->pNeighborBssDescription, sizeof(tSirNeighborBssDescription));
903 vos_mem_copy(pNeighborReportDesc->pNeighborBssDescription, &pNeighborRpt->sNeighborBssDescription[i],
904 sizeof(tSirNeighborBssDescription));
905
906#if defined WLAN_VOWIFI_DEBUG
907 smsLog( pMac, LOGE, "Received neighbor report with Neighbor BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
908 pNeighborRpt->sNeighborBssDescription[i].bssId[0],
909 pNeighborRpt->sNeighborBssDescription[i].bssId[1],
910 pNeighborRpt->sNeighborBssDescription[i].bssId[2],
911 pNeighborRpt->sNeighborBssDescription[i].bssId[3],
912 pNeighborRpt->sNeighborBssDescription[i].bssId[4],
913 pNeighborRpt->sNeighborBssDescription[i].bssId[5]);
914#endif
915
916 /* Calculate the roam score based on the BSS Capability in the BSSID Information and store it in Neighbor report Desc */
917 rrmCalculateNeighborAPRoamScore(pMac, pNeighborReportDesc);
918
919 /* Store the Neighbor report Desc in the cache based on the roam score */
920 if ( pNeighborReportDesc->roamScore > 0)
921 {
922 rrmStoreNeighborRptByRoamScore(pMac, pNeighborReportDesc);
923 }
924 else
925 {
926 smsLog(pMac, LOGE, FL("Roam score of BSSID %02x:%02x:%02x:%02x:%02x:%02x is 0, Ignoring.."),
927 pNeighborRpt->sNeighborBssDescription[i].bssId[0],
928 pNeighborRpt->sNeighborBssDescription[i].bssId[1],
929 pNeighborRpt->sNeighborBssDescription[i].bssId[2],
930 pNeighborRpt->sNeighborBssDescription[i].bssId[3],
931 pNeighborRpt->sNeighborBssDescription[i].bssId[4],
932 pNeighborRpt->sNeighborBssDescription[i].bssId[5]);
933
934 vos_mem_free(pNeighborReportDesc->pNeighborBssDescription);
935 vos_mem_free(pNeighborReportDesc);
936 }
937 }
938end:
939
940 if (!csrLLCount(&pMac->rrm.rrmSmeContext.neighborReportCache))
941 vosStatus = VOS_STATUS_E_FAILURE;
942
943 /* Received a report from AP. Indicate SUCCESS to the caller if there are some valid reports */
944 rrmIndicateNeighborReportResult(pMac, vosStatus);
945
946 return status;
947}
948/*--------------------------------------------------------------------------
949 \brief sme_RrmMsgProcessor() - sme_ProcessMsg() calls this function for the
950 messages that are handled by SME RRM module.
951
952 \param pMac - Pointer to the global MAC parameter structure.
953 \param msg_type - the type of msg passed by PE as defined in wniApi.h
954 \param pMsgBuf - a pointer to a buffer that maps to various structures base
955 on the message type.
956 The beginning of the buffer can always map to tSirSmeRsp.
957
958 \return eHAL_STATUS_SUCCESS - Validation is successful.
959
960 \sa
961
962 --------------------------------------------------------------------------*/
963eHalStatus sme_RrmMsgProcessor( tpAniSirGlobal pMac, v_U16_t msg_type,
964 void *pMsgBuf)
965{
966 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
967 FL(" Msg = %d for RRM measurement\n") , msg_type );
968
969 //switch on the msg type & make the state transition accordingly
970 switch(msg_type)
971 {
972 case eWNI_SME_NEIGHBOR_REPORT_IND:
973 sme_RrmProcessNeighborReport( pMac, pMsgBuf );
974 break;
975
976 case eWNI_SME_BEACON_REPORT_REQ_IND:
977 sme_RrmProcessBeaconReportReqInd( pMac, pMsgBuf );
978 break;
979
980 default:
981 //err msg
982 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
983 FL("sme_RrmMsgProcessor:unknown msg type = %d\n"), msg_type);
984
985 break;
986 }
987
988 return eHAL_STATUS_SUCCESS;
989}
990
991/* ---------------------------------------------------------------------------
992
993 \fn rrmIterMeasTimerHandle
994
995 \brief Timer handler to handlet the timeout condition when a specific BT
996
997 stop event does not come back, in which case to restore back the
998
999 heartbeat timer.
1000
1001 \param pMac - The handle returned by macOpen.
1002
1003 \return VOID
1004
1005 ---------------------------------------------------------------------------*/
1006
1007void rrmIterMeasTimerHandle( v_PVOID_t userData )
1008{
1009 tpAniSirGlobal pMac = (tpAniSirGlobal) userData;
1010#if defined WLAN_VOWIFI_DEBUG
1011 smsLog( pMac, LOGE, "Randomization timer expired...send on next channel \n");
1012#endif
1013 //Issue a scan req for next channel.
1014 sme_RrmIssueScanReq( pMac );
1015}
1016
1017/* ---------------------------------------------------------------------------
1018
1019 \fn rrmNeighborRspTimeoutHandler
1020
1021 \brief Timer handler to handle the timeout condition when a neighbor request is sent
1022 and no neighbor response is received from the AP
1023
1024 \param pMac - The handle returned by macOpen.
1025
1026 \return VOID
1027
1028---------------------------------------------------------------------------*/
1029
1030void rrmNeighborRspTimeoutHandler
1031( v_PVOID_t userData )
1032{
1033 tpAniSirGlobal pMac = (tpAniSirGlobal) userData;
1034#if defined WLAN_VOWIFI_DEBUG
1035 smsLog( pMac, LOGE, "Neighbor Response timed out \n");
1036#endif
1037 rrmIndicateNeighborReportResult(pMac, VOS_STATUS_E_FAILURE);
1038 return;
1039}
1040
1041/* ---------------------------------------------------------------------------
1042
1043 \fn rrmOpen
1044
1045 \brief
1046
1047 \param pMac - The handle returned by macOpen.
1048
1049 \return VOS_STATUS
1050
1051 VOS_STATUS_E_FAILURE success
1052
1053 VOS_STATUS_SUCCESS failure
1054
1055 ---------------------------------------------------------------------------*/
1056
1057VOS_STATUS rrmOpen (tpAniSirGlobal pMac)
1058
1059{
1060
1061 VOS_STATUS vosStatus;
1062 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
1063 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1064
1065 pSmeRrmContext->rrmConfig.maxRandnInterval = 50; //ms
1066
1067 vosStatus = vos_timer_init( &pSmeRrmContext->IterMeasTimer,
1068
1069 VOS_TIMER_TYPE_SW,
1070
1071 rrmIterMeasTimerHandle,
1072
1073 (void*) pMac);
1074
1075 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
1076
1077 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "rrmOpen: Fail to init timer");
1078
1079 return VOS_STATUS_E_FAILURE;
1080 }
1081
1082 vosStatus = vos_timer_init( &pSmeRrmContext->neighborReqControlInfo.neighborRspWaitTimer,
1083
1084 VOS_TIMER_TYPE_SW,
1085
1086 rrmNeighborRspTimeoutHandler,
1087
1088 (void*) pMac);
1089
1090 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
1091
1092 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "rrmOpen: Fail to init timer");
1093
1094 return VOS_STATUS_E_FAILURE;
1095 }
1096
1097 pSmeRrmContext->neighborReqControlInfo.isNeighborRspPending = eANI_BOOLEAN_FALSE;
1098
1099 halStatus = csrLLOpen(pMac->hHdd, &pSmeRrmContext->neighborReportCache);
1100 if (eHAL_STATUS_SUCCESS != halStatus)
1101 {
1102 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "rrmOpen: Fail to open neighbor cache result");
1103 return VOS_STATUS_E_FAILURE;
1104 }
1105
1106 return VOS_STATUS_SUCCESS;
1107}
1108
1109
1110/* ---------------------------------------------------------------------------
1111
1112 \fn rrmClose
1113
1114 \brief
1115
1116 \param pMac - The handle returned by macOpen.
1117
1118 \return VOS_STATUS
1119
1120 VOS_STATUS_E_FAILURE success
1121
1122 VOS_STATUS_SUCCESS failure
1123
1124 ---------------------------------------------------------------------------*/
1125
1126VOS_STATUS rrmClose (tpAniSirGlobal pMac)
1127
1128{
1129
1130 VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
1131 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
1132
1133 if( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState( &pSmeRrmContext->IterMeasTimer ) )
1134 {
1135 vosStatus = vos_timer_stop( &pSmeRrmContext->IterMeasTimer );
1136 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001137 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001138 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("Timer stop fail") );
1139 }
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001140 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001141
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001142 vosStatus = vos_timer_destroy( &pSmeRrmContext->IterMeasTimer );
1143 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1144 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001145
1146 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, FL("Fail to destroy timer") );
1147
1148 }
1149
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001150 if( VOS_TIMER_STATE_RUNNING ==
1151 vos_timer_getCurrentState( &pSmeRrmContext->neighborReqControlInfo.neighborRspWaitTimer ) )
1152 {
1153 vosStatus = vos_timer_stop( &pSmeRrmContext->neighborReqControlInfo.neighborRspWaitTimer );
1154 if(!VOS_IS_STATUS_SUCCESS(vosStatus))
1155 {
1156 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, FL("Timer stop fail") );
1157 }
1158 }
1159
1160 vosStatus = vos_timer_destroy( &pSmeRrmContext->neighborReqControlInfo.neighborRspWaitTimer );
1161 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
1162 {
1163 VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, FL("Fail to destroy timer") );
1164
1165 }
1166
Jeff Johnson295189b2012-06-20 16:38:30 -07001167 rrmLLPurgeNeighborCache(pMac, &pSmeRrmContext->neighborReportCache);
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001168
Jeff Johnson295189b2012-06-20 16:38:30 -07001169 csrLLClose(&pSmeRrmContext->neighborReportCache);
1170
1171 return vosStatus;
1172
1173}
1174
1175
1176
1177
1178/* ---------------------------------------------------------------------------
1179
1180 \fn rrmReady
1181
1182 \brief fn
1183
1184 \param pMac - The handle returned by macOpen.
1185
1186 \return VOS_STATUS
1187
1188 ---------------------------------------------------------------------------*/
1189
1190VOS_STATUS rrmReady (tpAniSirGlobal pMac)
1191
1192{
1193
1194 return VOS_STATUS_SUCCESS;
1195}
1196
1197/* ---------------------------------------------------------------------------
1198
1199 \fn rrmChangeDefaultConfigParam
1200 \brief fn
1201
1202 \param pMac - The handle returned by macOpen.
1203 \param pRrmConfig - pointer to new rrm configs.
1204
1205 \return VOS_STATUS
1206
1207 ---------------------------------------------------------------------------*/
1208VOS_STATUS rrmChangeDefaultConfigParam(tpAniSirGlobal pMac, tpRrmConfigParam pRrmConfig)
1209{
1210 vos_mem_copy( &pMac->rrm.rrmSmeContext.rrmConfig, pRrmConfig, sizeof( tRrmConfigParam ) );
1211
1212 return VOS_STATUS_SUCCESS;
1213}
1214
1215/* ---------------------------------------------------------------------------
1216
1217 \fn smeRrmGetFirstBssEntryFromNeighborCache()
1218
1219 \brief This function returns the first entry from the neighbor cache to the caller
1220
1221 \param pMac - The handle returned by macOpen.
1222
1223 \return VOID
1224
1225---------------------------------------------------------------------------*/
1226tRrmNeighborReportDesc* smeRrmGetFirstBssEntryFromNeighborCache( tpAniSirGlobal pMac)
1227{
1228 tListElem *pEntry;
1229 tRrmNeighborReportDesc *pTempBssEntry = NULL;
1230 tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
1231
1232
1233 pEntry = csrLLPeekHead( &pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK );
1234
1235 if(!pEntry || !csrLLCount(&pSmeRrmContext->neighborReportCache))
1236 {
1237 //list empty
1238 smsLog(pMac, LOGW, FL("List empty\n"));
1239 return NULL;
1240 }
1241
1242 pTempBssEntry = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List );
1243
1244 return pTempBssEntry;
1245}
1246
1247/* ---------------------------------------------------------------------------
1248
1249 \fn smeRrmGetNextBssEntryFromNeighborCache()
1250
1251 \brief This function returns the entry next to the given entry from the
1252 neighbor cache to the caller
1253
1254 \param pMac - The handle returned by macOpen.
1255
1256 \return VOID
1257
1258---------------------------------------------------------------------------*/
1259tRrmNeighborReportDesc* smeRrmGetNextBssEntryFromNeighborCache( tpAniSirGlobal pMac,
1260 tpRrmNeighborReportDesc pBssEntry)
1261{
1262 tListElem *pEntry;
1263 tRrmNeighborReportDesc *pTempBssEntry = NULL;
1264
1265 pEntry = csrLLNext(&pMac->rrm.rrmSmeContext.neighborReportCache, &pBssEntry->List, LL_ACCESS_LOCK);
1266
1267 if(!pEntry)
1268 {
1269 //list empty
1270 smsLog(pMac, LOGW, FL("List empty\n"));
1271 return NULL;
1272 }
1273
1274 pTempBssEntry = GET_BASE_ADDR( pEntry, tRrmNeighborReportDesc, List );
1275
1276 return pTempBssEntry;
1277}
1278
1279#ifdef FEATURE_WLAN_CCX
1280void csrCcxSendAdjacentApRepMsg(tpAniSirGlobal pMac, tCsrRoamSession *pSession)
1281{
1282 tpSirAdjacentApRepInd pAdjRep;
1283 tANI_U16 length;
1284 tANI_U32 roamTS2;
1285
1286 smsLog( pMac, LOG1, "Adjacent AP Report Msg to PE\n");
1287
1288 length = sizeof(tSirAdjacentApRepInd );
1289 pAdjRep = vos_mem_malloc ( length );
1290
1291 if ( NULL == pAdjRep )
1292 {
1293 smsLog( pMac, LOGP, "Unable to allocate memory for Adjacent AP report");
1294 return;
1295 }
1296
1297 vos_mem_zero( pAdjRep, length );
1298 pAdjRep->messageType = eWNI_SME_CCX_ADJACENT_AP_REPORT;
1299 pAdjRep->length = length;
1300 pAdjRep->channelNum = pSession->prevOpChannel;
1301 vos_mem_copy( pAdjRep->bssid, &pSession->connectedProfile.bssid, sizeof(tSirMacAddr) );
1302 vos_mem_copy( pAdjRep->prevApMacAddr, &pSession->prevApBssid, sizeof(tSirMacAddr) );
1303 vos_mem_copy( &pAdjRep->prevApSSID, &pSession->prevApSSID, sizeof(tSirMacSSid) );
1304 roamTS2 = vos_timer_get_system_time();
1305 pAdjRep->tsmRoamdelay = roamTS2 - pSession->roamTS1;
1306 pAdjRep->roamReason =SIR_CCX_ASSOC_REASON_UNSPECIFIED;
1307 pAdjRep->clientDissSecs =(pAdjRep->tsmRoamdelay/1000);
1308
1309 palSendMBMessage(pMac->hHdd, pAdjRep);
1310
1311 return;
1312}
1313#endif /* FEATURE_WLAN_CCX */
1314#endif