blob: 1b99e875ac4045196f9d75198a28dd7cbc887e62 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
2 * Copyright (c) 2012, Code Aurora Forum. 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 L I M _ P 2 P . C
24
25 OVERVIEW:
26
27 This software unit holds the implementation of the WLAN Protocol Engine for
28 P2P.
29
30 Copyright (c) 2011 QUALCOMM Incorporated.
31 All Rights Reserved.
32 Qualcomm Confidential and Proprietary
33===========================================================================*/
34
35/*===========================================================================
36
37 EDIT HISTORY FOR FILE
38
39
40 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
42
43
44 $Header$$DateTime$$Author$
45
46
47 when who what, where, why
48---------- --- --------------------------------------------------------
492011-05-02 djindal Corrected file indentation and changed remain on channel
50 handling for concurrency.
51===========================================================================*/
52
53
54#ifdef WLAN_FEATURE_P2P
55#include "limUtils.h"
56#include "limSessionUtils.h"
57#include "wlan_qct_wda.h"
58
59#define PROBE_RSP_IE_OFFSET 36
60#define BSSID_OFFSET 16
61#define ADDR2_OFFSET 10
62#define ACTION_OFFSET 24
Jeff Johnsone7245742012-09-05 17:12:55 -070063#define LIM_MIN_REM_TIME_FOR_TX_ACTION_FRAME 30
64#define LIM_MIN_REM_TIME_EXT_FOR_TX_ACTION_FRAME 40
Jeff Johnson295189b2012-06-20 16:38:30 -070065
66
67
68void limRemainOnChnlSuspendLinkHdlr(tpAniSirGlobal pMac, eHalStatus status,
69 tANI_U32 *data);
70void limRemainOnChnlSetLinkStat(tpAniSirGlobal pMac, eHalStatus status,
71 tANI_U32 *data, tpPESession psessionEntry);
72void limExitRemainOnChannel(tpAniSirGlobal pMac, eHalStatus status,
73 tANI_U32 *data, tpPESession psessionEntry);
74void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data);
75extern tSirRetStatus limSetLinkState(
76 tpAniSirGlobal pMac, tSirLinkState state,
77 tSirMacAddr bssId, tSirMacAddr selfMacAddr,
78 tpSetLinkStateCallback callback, void *callbackArg);
79
80static tSirRetStatus limCreateSessionForRemainOnChn(tpAniSirGlobal pMac, tPESession **ppP2pSession);
Jeff Johnsone7245742012-09-05 17:12:55 -070081eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess);
Jeff Johnson295189b2012-06-20 16:38:30 -070082/*------------------------------------------------------------------
83 *
84 * Below function is callback function, it is called when
85 * WDA_SET_LINK_STATE_RSP is received from WDI. callback function for
86 * P2P of limSetLinkState
87 *
88 *------------------------------------------------------------------*/
89void limSetLinkStateP2PCallback(tpAniSirGlobal pMac, void *callbackArg)
90{
91 //Send Ready on channel indication to SME
92 if(pMac->lim.gpLimRemainOnChanReq)
93 {
94 limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RDY_IND, eHAL_STATUS_SUCCESS,
95 pMac->lim.gpLimRemainOnChanReq->sessionId, 0);
96 }
97 else
98 {
99 //This is possible in case remain on channel is aborted
100 limLog( pMac, LOGE, FL(" NULL pointer of gpLimRemainOnChanReq") );
101 }
102}
103
104/*------------------------------------------------------------------
105 *
106 * Remain on channel req handler. Initiate the INIT_SCAN, CHN_CHANGE
107 * and SET_LINK Request from SME, chnNum and duration to remain on channel.
108 *
109 *------------------------------------------------------------------*/
110
111
112int limProcessRemainOnChnlReq(tpAniSirGlobal pMac, tANI_U32 *pMsg)
113{
114 tANI_U8 i;
115 tpPESession psessionEntry;
116#ifdef WLAN_FEATURE_P2P_INTERNAL
117 tpPESession pP2pSession;
118#endif
119
120 tSirRemainOnChnReq *MsgBuff = (tSirRemainOnChnReq *)pMsg;
121 pMac->lim.gpLimRemainOnChanReq = MsgBuff;
122
123 for (i =0; i < pMac->lim.maxBssId;i++)
124 {
125 psessionEntry = peFindSessionBySessionId(pMac,i);
126
127 if ( (psessionEntry != NULL) )
128 {
129 if (psessionEntry->currentOperChannel == MsgBuff->chnNum)
130 {
131 tANI_U32 val;
132 tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
133
Jeff Johnsone7245742012-09-05 17:12:55 -0700134 pMac->lim.p2pRemOnChanTimeStamp = vos_timer_get_system_time();
135 pMac->lim.gTotalScanDuration = MsgBuff->duration;
Jeff Johnson295189b2012-06-20 16:38:30 -0700136
137 /* get the duration from the request */
138 val = SYS_MS_TO_TICKS(MsgBuff->duration);
139
140 limLog( pMac, LOGE, "Start listen duration = %d", val);
141 if (tx_timer_change(
142 &pMac->lim.limTimers.gLimRemainOnChannelTimer, val, 0)
143 != TX_SUCCESS)
144 {
145 limLog(pMac, LOGP,
146 FL("Unable to change remain on channel Timer val\n"));
147 goto error;
148 }
149 else if(TX_SUCCESS != tx_timer_activate(
150 &pMac->lim.limTimers.gLimRemainOnChannelTimer))
151 {
152 limLog(pMac, LOGP,
153 FL("Unable to activate remain on channel Timer\n"));
154 limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER);
155 goto error;
156 }
157
158#ifdef WLAN_FEATURE_P2P_INTERNAL
159 //Session is needed to send probe rsp
160 if(eSIR_SUCCESS != limCreateSessionForRemainOnChn(pMac, &pP2pSession))
161 {
162 limLog( pMac, LOGE, "Unable to create session");
163 goto error;
164 }
165#endif
166
167 if ((limSetLinkState(pMac, eSIR_LINK_LISTEN_STATE,
168 nullBssid, pMac->lim.gSelfMacAddr,
169 limSetLinkStateP2PCallback, NULL)) != eSIR_SUCCESS)
170 {
171 limLog( pMac, LOGE, "Unable to change link state");
172 goto error;
173 }
174 return FALSE;
175 }
176 }
177 }
178
179 pMac->lim.gLimPrevMlmState = pMac->lim.gLimMlmState;
180 pMac->lim.gLimMlmState = eLIM_MLM_P2P_LISTEN_STATE;
181
182 pMac->lim.gTotalScanDuration = MsgBuff->duration;
183
184 /* 1st we need to suspend link with callback to initiate change channel */
185 limSuspendLink(pMac, eSIR_CHECK_LINK_TRAFFIC_BEFORE_SCAN,
186 limRemainOnChnlSuspendLinkHdlr, NULL);
187 return FALSE;
188
189error:
190 limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL);
191 /* pMsg is freed by the caller */
192 return FALSE;
193}
194
195
196tSirRetStatus limCreateSessionForRemainOnChn(tpAniSirGlobal pMac, tPESession **ppP2pSession)
197{
198 tSirRetStatus nSirStatus = eSIR_FAILURE;
199 tpPESession psessionEntry;
200 tANI_U8 sessionId;
201 tANI_U32 val;
202
203 if(pMac->lim.gpLimRemainOnChanReq && ppP2pSession)
204 {
205 if((psessionEntry = peCreateSession(pMac,
206 pMac->lim.gpLimRemainOnChanReq->selfMacAddr, &sessionId, 1)) == NULL)
207 {
208 limLog(pMac, LOGE, FL("Session Can not be created \n"));
209 /* send remain on chn failure */
210 return nSirStatus;
211 }
212 /* Store PE sessionId in session Table */
213 psessionEntry->peSessionId = sessionId;
214
215 psessionEntry->limSystemRole = eLIM_P2P_DEVICE_ROLE;
216 CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_RATES_11A,
217 psessionEntry->rateSet.rate, val , SIR_MAC_MAX_NUMBER_OF_RATES );
218 psessionEntry->rateSet.numRates = val;
219
220 CFG_GET_STR( nSirStatus, pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
221 psessionEntry->extRateSet.rate, val,
222 WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN );
223 psessionEntry->extRateSet.numRates = val;
224
225 sirCopyMacAddr(psessionEntry->selfMacAddr,
226 pMac->lim.gpLimRemainOnChanReq->selfMacAddr);
227
228 psessionEntry->currentOperChannel = pMac->lim.gpLimRemainOnChanReq->chnNum;
229 nSirStatus = eSIR_SUCCESS;
230 *ppP2pSession = psessionEntry;
231 }
232
233 return nSirStatus;
234}
235
236
237/*------------------------------------------------------------------
238 *
239 * limSuspenLink callback, on success link suspend, trigger change chn
240 *
241 *
242 *------------------------------------------------------------------*/
243
244tSirRetStatus limRemainOnChnlChangeChnReq(tpAniSirGlobal pMac,
245 eHalStatus status, tANI_U32 *data)
246{
247 tpPESession psessionEntry;
248 tANI_U8 sessionId = 0;
249 tSirRetStatus nSirStatus = eSIR_FAILURE;
250
251 if( NULL == pMac->lim.gpLimRemainOnChanReq )
252 {
253 //RemainOnChannel may have aborted
254 PELOGE(limLog( pMac, LOGE, FL(" gpLimRemainOnChanReq is NULL") );)
255 return nSirStatus;
256 }
257
258 /* The link is not suspended */
259 if (status != eHAL_STATUS_SUCCESS)
260 {
261 PELOGE(limLog( pMac, LOGE, FL(" Suspend link Failure ") );)
262 goto error;
263 }
264
265
266 if((psessionEntry = peFindSessionByBssid(
267 pMac,pMac->lim.gpLimRemainOnChanReq->selfMacAddr, &sessionId)) != NULL)
268 {
269 goto change_channel;
270 }
271 else /* Session Entry does not exist for given BSSId */
272 {
273 /* Try to Create a new session */
274 if(eSIR_SUCCESS != limCreateSessionForRemainOnChn(pMac, &psessionEntry))
275 {
276 limLog(pMac, LOGE, FL("Session Can not be created \n"));
277 /* send remain on chn failure */
278 goto error;
279 }
280 }
281
282change_channel:
283 /* change channel to the requested by RemainOn Chn*/
284 limChangeChannelWithCallback(pMac,
285 pMac->lim.gpLimRemainOnChanReq->chnNum,
286 limRemainOnChnlSetLinkStat, NULL, psessionEntry);
287 return eSIR_SUCCESS;
288
289error:
290 limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL);
291 return eSIR_FAILURE;
292}
293
294void limRemainOnChnlSuspendLinkHdlr(tpAniSirGlobal pMac, eHalStatus status,
295 tANI_U32 *data)
296{
297 limRemainOnChnlChangeChnReq(pMac, status, data);
298 return;
299}
300
301/*------------------------------------------------------------------
302 *
303 * Set the LINK state to LISTEN to allow only PROBE_REQ and Action frames
304 *
305 *------------------------------------------------------------------*/
306void limRemainOnChnlSetLinkStat(tpAniSirGlobal pMac, eHalStatus status,
307 tANI_U32 *data, tpPESession psessionEntry)
308{
309 tANI_U32 val;
310 tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq;
311 tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
312
313 if (status != eHAL_STATUS_SUCCESS)
314 {
315 limLog( pMac, LOGE, "%s: Change channel not successful\n");
316 goto error1;
317 }
318
319 // Start timer here to come back to operating channel.
320 pMac->lim.limTimers.gLimRemainOnChannelTimer.sessionId =
321 psessionEntry->peSessionId;
Jeff Johnsone7245742012-09-05 17:12:55 -0700322 pMac->lim.p2pRemOnChanTimeStamp = vos_timer_get_system_time();
323 pMac->lim.gTotalScanDuration = MsgRemainonChannel->duration;
Jeff Johnson295189b2012-06-20 16:38:30 -0700324
325 /* get the duration from the request */
326 val = SYS_MS_TO_TICKS(MsgRemainonChannel->duration);
327
328 limLog( pMac, LOGE, "Start listen duration = %d", val);
329 if (tx_timer_change(&pMac->lim.limTimers.gLimRemainOnChannelTimer,
330 val, 0) != TX_SUCCESS)
331 {
332 /**
333 * Could not change Remain on channel Timer. Log error.
334 */
335 limLog(pMac, LOGP,
336 FL("Unable to change remain on channel Timer val\n"));
337 goto error;
338 }
339
340 if(TX_SUCCESS !=
341 tx_timer_activate(&pMac->lim.limTimers.gLimRemainOnChannelTimer))
342 {
343 limLog( pMac, LOGE,
344 "%s: remain on channel Timer Start Failed\n", __FUNCTION__);
345 goto error;
346 }
347
348 if ((limSetLinkState(pMac, eSIR_LINK_LISTEN_STATE,nullBssid,
349 pMac->lim.gSelfMacAddr, limSetLinkStateP2PCallback,
350 NULL)) != eSIR_SUCCESS)
351 {
352 limLog( pMac, LOGE, "Unable to change link state");
353 goto error;
354 }
355
356 return;
357error:
358 limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER);
359error1:
360 limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL);
361 return;
362}
363
364/*------------------------------------------------------------------
365 *
366 * limchannelchange callback, on success channel change, set the
367 * link_state to LISTEN
368 *
369 *------------------------------------------------------------------*/
370
371void limProcessRemainOnChnTimeout(tpAniSirGlobal pMac)
372{
373 tpPESession psessionEntry;
374 tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
375
Jeff Johnsone7245742012-09-05 17:12:55 -0700376 //Timer might get extended while Sending Action Frame
377 //In that case don't process Channel Timeout
378 if (tx_timer_running(&pMac->lim.limTimers.gLimRemainOnChannelTimer))
379 {
380 limLog( pMac, LOGE,
381 "still timer is running already and not processing limProcessRemainOnChnTimeout");
382 return;
383 }
384
Jeff Johnson295189b2012-06-20 16:38:30 -0700385 limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER);
386
387 if (NULL == pMac->lim.gpLimRemainOnChanReq)
388 {
389 limLog( pMac, LOGE, "No Remain on channel pending");
390 return;
391 }
392
393 /* get the previous valid LINK state */
394 if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, nullBssid,
395 pMac->lim.gSelfMacAddr, NULL, NULL) != eSIR_SUCCESS)
396 {
397 limLog( pMac, LOGE, "Unable to change link state");
398 return;
399 }
400
401 if (pMac->lim.gLimMlmState != eLIM_MLM_P2P_LISTEN_STATE )
402 {
403 limRemainOnChnRsp(pMac,eHAL_STATUS_SUCCESS, NULL);
404 }
405 else
406 {
407 /* get the session */
408 if((psessionEntry = peFindSessionBySessionId(pMac,
409 pMac->lim.limTimers.gLimRemainOnChannelTimer.sessionId))== NULL)
410 {
411 limLog(pMac, LOGE,
412 FL("Session Does not exist for given sessionID\n"));
413 goto error;
414 }
415
416 limExitRemainOnChannel(pMac, eHAL_STATUS_SUCCESS, NULL, psessionEntry);
417 return;
418error:
419 limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL);
420 }
421 return;
422}
423
424
425/*------------------------------------------------------------------
426 *
427 * limchannelchange callback, on success channel change, set the link_state
428 * to LISTEN
429 *
430 *------------------------------------------------------------------*/
431
432void limExitRemainOnChannel(tpAniSirGlobal pMac, eHalStatus status,
433 tANI_U32 *data, tpPESession psessionEntry)
434{
435
436 if (status != eHAL_STATUS_SUCCESS)
437 {
438 PELOGE(limLog( pMac, LOGE, "Remain on Channel Failed\n");)
439 goto error;
440 }
441 //Set the resume channel to Any valid channel (invalid).
442 //This will instruct HAL to set it to any previous valid channel.
443 peSetResumeChannel(pMac, 0, 0);
444 limResumeLink(pMac, limRemainOnChnRsp, NULL);
445 return;
446error:
447 limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL);
448 return;
449}
450
451/*------------------------------------------------------------------
452 *
453 * Send remain on channel respone: Success/ Failure
454 *
455 *------------------------------------------------------------------*/
456void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data)
457{
458 tpPESession psessionEntry;
459 tANI_U8 sessionId;
460 tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq;
461 tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
462
463 if ( NULL == MsgRemainonChannel )
464 {
465 PELOGE(limLog( pMac, LOGP,
466 "%s: No Pointer for Remain on Channel Req\n", __FUNCTION__);)
467 return;
468 }
469
470 //Incase of the Remain on Channel Failure Case
471 //Cleanup Everything
472 if(eHAL_STATUS_FAILURE == status)
473 {
474 //Deactivate Remain on Channel Timer
475 limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER);
476
477 //Set the Link State to Idle
478 /* get the previous valid LINK state */
479 if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, nullBssid,
480 pMac->lim.gSelfMacAddr, NULL, NULL) != eSIR_SUCCESS)
481 {
482 limLog( pMac, LOGE, "Unable to change link state");
483 }
484
485 pMac->lim.gLimSystemInScanLearnMode = 0;
486 pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE;
487 }
488
489 /* delete the session */
490 if((psessionEntry = peFindSessionByBssid(pMac,
491 MsgRemainonChannel->selfMacAddr,&sessionId)) != NULL)
492 {
493 if ( eLIM_P2P_DEVICE_ROLE == psessionEntry->limSystemRole )
494 {
495 peDeleteSession( pMac, psessionEntry);
496 }
497 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700498
Jeff Johnson295189b2012-06-20 16:38:30 -0700499 /* Post the meessage to Sme */
500 limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP, status,
501 MsgRemainonChannel->sessionId, 0);
502
503 palFreeMemory( pMac->hHdd, pMac->lim.gpLimRemainOnChanReq );
504 pMac->lim.gpLimRemainOnChanReq = NULL;
505
506 pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState;
Jeff Johnsone7245742012-09-05 17:12:55 -0700507
508 /* If remain on channel timer expired and action frame is pending then
509 * indicaiton confirmation with status failure */
510 if (pMac->lim.actionFrameSessionId != 0xff)
511 {
512 limP2PActionCnf(pMac, 0);
513 }
514
Jeff Johnson295189b2012-06-20 16:38:30 -0700515 return;
516}
517
518/*------------------------------------------------------------------
519 *
520 * Indicate the Mgmt Frame received to SME to HDD callback
521 * handle Probe_req/Action frame currently
522 *
523 *------------------------------------------------------------------*/
524void limSendSmeMgmtFrameInd(
525 tpAniSirGlobal pMac, tANI_U8 frameType,
526 tANI_U8 *frame, tANI_U32 frameLen, tANI_U16 sessionId,
Jeff Johnsone7245742012-09-05 17:12:55 -0700527 tANI_U32 rxChannel, tpPESession psessionEntry)
Jeff Johnson295189b2012-06-20 16:38:30 -0700528{
529 tSirMsgQ mmhMsg;
530 tpSirSmeMgmtFrameInd pSirSmeMgmtFrame = NULL;
531 tANI_U16 length;
532
533 length = sizeof(tSirSmeMgmtFrameInd) + frameLen;
534
535 if( eHAL_STATUS_SUCCESS !=
536 palAllocateMemory( pMac->hHdd, (void **)&pSirSmeMgmtFrame, length ))
537 {
538 limLog(pMac, LOGP,
539 FL("palAllocateMemory failed for eWNI_SME_LISTEN_RSP\n"));
540 return;
541 }
542 palZeroMemory(pMac->hHdd, (void*)pSirSmeMgmtFrame, length);
543
544 pSirSmeMgmtFrame->mesgType = eWNI_SME_MGMT_FRM_IND;
545 pSirSmeMgmtFrame->mesgLen = length;
546 pSirSmeMgmtFrame->sessionId = sessionId;
547 pSirSmeMgmtFrame->frameType = frameType;
Jeff Johnsone7245742012-09-05 17:12:55 -0700548
549 /* work around for 5Ghz channel is not correct since rxhannel
550 * is 4 bits. So we don't indicate more than 16 channels
551 */
552 if( (VOS_FALSE ==
553 tx_timer_running(&pMac->lim.limTimers.gLimRemainOnChannelTimer)) &&
554 (psessionEntry != NULL) &&
555 (SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) )
556 {
557 pSirSmeMgmtFrame->rxChan = psessionEntry->currentOperChannel;
558 }
559 else
560 {
561 pSirSmeMgmtFrame->rxChan = rxChannel;
562 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700563
564 vos_mem_zero(pSirSmeMgmtFrame->frameBuf,frameLen);
565 vos_mem_copy(pSirSmeMgmtFrame->frameBuf,frame,frameLen);
566
567 mmhMsg.type = eWNI_SME_MGMT_FRM_IND;
568 mmhMsg.bodyptr = pSirSmeMgmtFrame;
569 mmhMsg.bodyval = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -0700570
571 if(VOS_TRUE == tx_timer_running(&pMac->lim.limTimers.gLimRemainOnChannelTimer) &&
572 ( (psessionEntry != NULL) && (psessionEntry->pePersona != VOS_P2P_GO_MODE)) &&
573 (frameType == SIR_MAC_MGMT_ACTION))
574 {
575 tANI_U32 curTime = vos_timer_get_system_time();
576 if((curTime - pMac->lim.p2pRemOnChanTimeStamp) > (pMac->lim.gTotalScanDuration - LIM_MIN_REM_TIME_FOR_TX_ACTION_FRAME))
577 {
578 unsigned int chanWaitTime, vStatus ;
579
580 limLog( pMac, LOG1, FL("Rx: Extend the gLimRemainOnChannelTimer"));
581
582 pMac->lim.p2pRemOnChanTimeStamp = vos_timer_get_system_time();
583 pMac->lim.gTotalScanDuration = LIM_MIN_REM_TIME_EXT_FOR_TX_ACTION_FRAME;
584
585 chanWaitTime = SYS_MS_TO_TICKS(40);
586 vStatus = tx_timer_deactivate(&pMac->lim.limTimers.gLimRemainOnChannelTimer);
587
588 if (VOS_STATUS_SUCCESS != vStatus)
589 {
590 limLog( pMac, LOGE, FL("Rx: Extend the gLimRemainOnChannelTimer"));
591 }
592
593 if (tx_timer_change(&pMac->lim.limTimers.gLimRemainOnChannelTimer, chanWaitTime, 0) != TX_SUCCESS)
594 {
595 limLog( pMac, LOGE, FL("Unable to change the gLimRemainOnChannelTimer"));
596 }
597
598 if (tx_timer_activate(&pMac->lim.limTimers.gLimRemainOnChannelTimer) != 0)
599 {
600 limLog( pMac, LOGE, FL("Unable to active the gLimRemainOnChannelTimer"));
601 }
602 }
603 }
604
Jeff Johnson295189b2012-06-20 16:38:30 -0700605 limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
606 return;
607} /*** end limSendSmeListenRsp() ***/
608
609
610eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, tANI_U32 txCompleteSuccess)
611{
Jeff Johnsone7245742012-09-05 17:12:55 -0700612 if (pMac->lim.actionFrameSessionId != 0xff)
613 {
614 /* The session entry might be invalid(0xff) action confirmation received after
615 * remain on channel timer expired */
616 limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
617 (txCompleteSuccess ? eSIR_SME_SUCCESS : eSIR_SME_SEND_ACTION_FAIL),
618 pMac->lim.actionFrameSessionId, 0);
619 pMac->lim.actionFrameSessionId = 0xff;
620 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700621
622 return eHAL_STATUS_SUCCESS;
623}
624
625
Jeff Johnsone7245742012-09-05 17:12:55 -0700626void limSetHtCaps(tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U8 *pIeStartPtr,tANI_U32 nBytes)
Jeff Johnson295189b2012-06-20 16:38:30 -0700627{
628 v_U8_t *pIe=NULL;
629 tDot11fIEHTCaps dot11HtCap;
630
Jeff Johnsone7245742012-09-05 17:12:55 -0700631 PopulateDot11fHTCaps(pMac, psessionEntry, &dot11HtCap);
Jeff Johnson295189b2012-06-20 16:38:30 -0700632 pIe = limGetIEPtr(pMac,pIeStartPtr, nBytes,
633 DOT11F_EID_HTCAPS,ONE_BYTE);
634 limLog( pMac, LOGE, FL("pIe 0x%x dot11HtCap.supportedMCSSet[0]=0x%x"),
635 (tANI_U32)pIe,dot11HtCap.supportedMCSSet[0]);
636 if(pIe)
637 {
638 tHtCaps *pHtcap = (tHtCaps *)&pIe[2]; //convert from unpacked to packed structure
639 pHtcap->advCodingCap = dot11HtCap.advCodingCap;
640 pHtcap->supportedChannelWidthSet = dot11HtCap.supportedChannelWidthSet;
641 pHtcap->mimoPowerSave = dot11HtCap.mimoPowerSave;
642 pHtcap->greenField = dot11HtCap.greenField;
643 pHtcap->shortGI20MHz = dot11HtCap.shortGI20MHz;
644 pHtcap->shortGI40MHz = dot11HtCap.shortGI40MHz;
645 pHtcap->txSTBC = dot11HtCap.txSTBC;
646 pHtcap->rxSTBC = dot11HtCap.rxSTBC;
647 pHtcap->delayedBA = dot11HtCap.delayedBA ;
648 pHtcap->maximalAMSDUsize = dot11HtCap.maximalAMSDUsize;
649 pHtcap->dsssCckMode40MHz = dot11HtCap.dsssCckMode40MHz;
650 pHtcap->psmp = dot11HtCap.psmp;
651 pHtcap->stbcControlFrame = dot11HtCap.stbcControlFrame;
652 pHtcap->lsigTXOPProtection = dot11HtCap.lsigTXOPProtection;
653 pHtcap->maxRxAMPDUFactor = dot11HtCap.maxRxAMPDUFactor;
654 pHtcap->mpduDensity = dot11HtCap.mpduDensity;
655 palCopyMemory( pMac->hHdd, (void *)pHtcap->supportedMCSSet,
656 (void *)(dot11HtCap.supportedMCSSet),
657 sizeof(pHtcap->supportedMCSSet));
658 pHtcap->pco = dot11HtCap.pco;
659 pHtcap->transitionTime = dot11HtCap.transitionTime;
660 pHtcap->mcsFeedback = dot11HtCap.mcsFeedback;
661 pHtcap->txBF = dot11HtCap.txBF;
662 pHtcap->rxStaggeredSounding = dot11HtCap.rxStaggeredSounding;
663 pHtcap->txStaggeredSounding = dot11HtCap.txStaggeredSounding;
664 pHtcap->rxZLF = dot11HtCap.rxZLF;
665 pHtcap->txZLF = dot11HtCap.txZLF;
666 pHtcap->implicitTxBF = dot11HtCap.implicitTxBF;
667 pHtcap->calibration = dot11HtCap.calibration;
668 pHtcap->explicitCSITxBF = dot11HtCap.explicitCSITxBF;
669 pHtcap->explicitUncompressedSteeringMatrix =
670 dot11HtCap.explicitUncompressedSteeringMatrix;
671 pHtcap->explicitBFCSIFeedback = dot11HtCap.explicitBFCSIFeedback;
672 pHtcap->explicitUncompressedSteeringMatrixFeedback =
673 dot11HtCap.explicitUncompressedSteeringMatrixFeedback;
674 pHtcap->explicitCompressedSteeringMatrixFeedback =
675 dot11HtCap.explicitCompressedSteeringMatrixFeedback;
676 pHtcap->csiNumBFAntennae = dot11HtCap.csiNumBFAntennae;
677 pHtcap->uncompressedSteeringMatrixBFAntennae =
678 dot11HtCap.uncompressedSteeringMatrixBFAntennae;
679 pHtcap->compressedSteeringMatrixBFAntennae =
680 dot11HtCap.compressedSteeringMatrixBFAntennae;
681 pHtcap->antennaSelection = dot11HtCap.antennaSelection;
682 pHtcap->explicitCSIFeedbackTx = dot11HtCap.explicitCSIFeedbackTx;
683 pHtcap->antennaIndicesFeedbackTx = dot11HtCap.antennaIndicesFeedbackTx;
684 pHtcap->explicitCSIFeedback = dot11HtCap.explicitCSIFeedback;
685 pHtcap->antennaIndicesFeedback = dot11HtCap.antennaIndicesFeedback;
686 pHtcap->rxAS = dot11HtCap.rxAS;
687 pHtcap->txSoundingPPDUs = dot11HtCap.txSoundingPPDUs;
688 }
689}
690
691
692void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
693{
694 tSirMbMsgP2p *pMbMsg = (tSirMbMsgP2p *)pMsg->bodyptr;
695 tANI_U32 nBytes;
696 tANI_U8 *pFrame;
697 void *pPacket;
698 eHalStatus halstatus;
699 tANI_U8 txFlag = 0;
700 tpSirMacFrameCtl pFc = (tpSirMacFrameCtl ) pMbMsg->data;
701 tANI_U8 noaLen = 0;
702 tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN];
703 tANI_U8 origLen = 0;
704 tANI_U8 sessionId = 0;
705 v_U8_t *pP2PIe = NULL;
706 tpPESession psessionEntry;
707 v_U8_t *pPresenceRspNoaAttr = NULL;
708 v_U8_t *pNewP2PIe = NULL;
709 v_U16_t remainLen = 0;
710
711 nBytes = pMbMsg->msgLen - sizeof(tSirMbMsg);
712
713 limLog( pMac, LOG1, FL("sending pFc->type=%d pFc->subType=%d"),
714 pFc->type, pFc->subType);
715
716 psessionEntry = peFindSessionByBssid(pMac,
717 (tANI_U8*)pMbMsg->data + BSSID_OFFSET, &sessionId);
718
719 /* Check for session corresponding to ADDR2 As Supplicant is filling
720 ADDR2 with BSSID */
721 if( NULL == psessionEntry )
722 {
723 psessionEntry = peFindSessionByBssid(pMac,
724 (tANI_U8*)pMbMsg->data + ADDR2_OFFSET, &sessionId);
725 }
726
727 if( NULL == psessionEntry )
728 {
729 tANI_U8 isSessionActive = 0;
730 tANI_U8 i;
731
732 /* If we are not able to find psessionEntry entry, then try to find
733 active session, if found any active sessions then send the
734 action frame, If no active sessions found then drop the frame */
735 for (i =0; i < pMac->lim.maxBssId;i++)
736 {
737 psessionEntry = peFindSessionBySessionId(pMac,i);
738 if ( NULL != psessionEntry)
739 {
740 isSessionActive = 1;
741 break;
742 }
743 }
744 if( !isSessionActive )
745 {
746 limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
747 eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0);
748 return;
749 }
750 }
751
752 if ((SIR_MAC_MGMT_FRAME == pFc->type)&&
753 ((SIR_MAC_MGMT_PROBE_RSP == pFc->subType)||
754 (SIR_MAC_MGMT_ACTION == pFc->subType)))
755 {
756 //if this is a probe RSP being sent from wpa_supplicant
757 if (SIR_MAC_MGMT_PROBE_RSP == pFc->subType)
758 {
759 //get proper offset for Probe RSP
760 pP2PIe = limGetP2pIEPtr(pMac,
761 (tANI_U8*)pMbMsg->data + PROBE_RSP_IE_OFFSET,
762 nBytes - PROBE_RSP_IE_OFFSET);
763 while ((NULL != pP2PIe) && (SIR_MAC_MAX_IE_LENGTH == pP2PIe[1]))
764 {
765 remainLen = nBytes - (pP2PIe - (tANI_U8*)pMbMsg->data);
766 if (remainLen > 2)
767 {
768 pNewP2PIe = limGetP2pIEPtr(pMac,
769 pP2PIe+SIR_MAC_MAX_IE_LENGTH + 2, remainLen);
770 }
771 if (pNewP2PIe)
772 {
773 pP2PIe = pNewP2PIe;
774 pNewP2PIe = NULL;
775 }
776 else
777 {
778 break;
779 }
780 } //end of while
781 }
782 else
783 {
784 if (SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY ==
785 *((v_U8_t *)pMbMsg->data+ACTION_OFFSET))
786 {
787 tpSirMacP2PActionFrameHdr pActionHdr =
788 (tpSirMacP2PActionFrameHdr)((v_U8_t *)pMbMsg->data +
789 ACTION_OFFSET);
790 if ( palEqualMemory( pMac->hHdd, pActionHdr->Oui,
791 SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE ) &&
792 (SIR_MAC_ACTION_P2P_SUBTYPE_PRESENCE_RSP ==
793 pActionHdr->OuiSubType))
794 { //In case of Presence RSP response
795 pP2PIe = limGetP2pIEPtr(pMac,
796 (v_U8_t *)pMbMsg->data + ACTION_OFFSET +
797 sizeof(tSirMacP2PActionFrameHdr),
798 (nBytes - ACTION_OFFSET -
799 sizeof(tSirMacP2PActionFrameHdr)));
800 if( NULL != pP2PIe )
801 {
802 //extract the presence of NoA attribute inside P2P IE
803 pPresenceRspNoaAttr =
804 limGetIEPtr(pMac,pP2PIe + SIR_P2P_IE_HEADER_LEN,
805 pP2PIe[1], SIR_P2P_NOA_ATTR,TWO_BYTE);
806 }
807 }
808 }
809 }
810
811 if (pP2PIe != NULL)
812 {
813 //get NoA attribute stream P2P IE
814 noaLen = limGetNoaAttrStream(pMac, noaStream, psessionEntry);
815 //need to append NoA attribute in P2P IE
816 if (noaLen > 0)
817 {
818 origLen = pP2PIe[1];
819 //if Presence Rsp has NoAttr
820 if (pPresenceRspNoaAttr)
821 {
822 v_U16_t noaAttrLen = pPresenceRspNoaAttr[1] |
823 (pPresenceRspNoaAttr[2]<<8);
824 /*One byte for attribute, 2bytes for length*/
825 origLen -= (noaAttrLen + 1 + 2);
826 //remove those bytes to copy
827 nBytes -= (noaAttrLen + 1 + 2);
828 //remove NoA from original Len
829 pP2PIe[1] = origLen;
830 }
831 if ((pP2PIe[1] + (tANI_U16)noaLen)> SIR_MAC_MAX_IE_LENGTH)
832 {
833 //Form the new NoA Byte array in multiple P2P IEs
834 noaLen = limGetNoaAttrStreamInMultP2pIes(pMac, noaStream,
835 noaLen,((pP2PIe[1] + (tANI_U16)noaLen)-
836 SIR_MAC_MAX_IE_LENGTH));
837 pP2PIe[1] = SIR_MAC_MAX_IE_LENGTH;
838 }
839 else
840 {
841 pP2PIe[1] += noaLen; //increment the length of P2P IE
842 }
843 nBytes += noaLen;
844 limLog( pMac, LOGE,
845 FL("noaLen=%d origLen=%d pP2PIe=0x%x"
846 " nBytes=%d nBytesToCopy=%d \n"),
847 noaLen,origLen,pP2PIe,nBytes,
848 ((pP2PIe + origLen + 2) - (v_U8_t *)pMbMsg->data));
849 }
850 }
851
852 if (SIR_MAC_MGMT_PROBE_RSP == pFc->subType)
853 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700854 limSetHtCaps( pMac, psessionEntry, (tANI_U8*)pMbMsg->data + PROBE_RSP_IE_OFFSET,
Jeff Johnson295189b2012-06-20 16:38:30 -0700855 nBytes);
856 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700857
858 /* The minimum wait for any action frame should be atleast 100 ms.
859 * If supplicant sends action frame at the end of already running remain on channel time
860 * Then there is a chance to miss the response of the frame. So increase the remain on channel
861 * time for all action frame to make sure that we receive the response frame */
862 if ((SIR_MAC_MGMT_ACTION == pFc->subType) &&
863 (0 != pMbMsg->wait))
864 {
865 if (tx_timer_running(&pMac->lim.limTimers.gLimRemainOnChannelTimer))
866 {
867 tANI_U32 val = 0;
868 tx_timer_deactivate(&pMac->lim.limTimers.gLimRemainOnChannelTimer);
869 /* get the duration from the request */
870 pMac->lim.p2pRemOnChanTimeStamp = vos_timer_get_system_time();
871 pMac->lim.gTotalScanDuration = pMbMsg->wait;
872
873 val = SYS_MS_TO_TICKS(pMbMsg->wait);
874
875 limLog(pMac, LOG1,
876 FL("Tx: Extending the gLimRemainOnChannelTimer\n"));
877 if (tx_timer_change(
878 &pMac->lim.limTimers.gLimRemainOnChannelTimer, val, 0)
879 != TX_SUCCESS)
880 {
881 limLog(pMac, LOGP,
882 FL("Unable to change remain on channel Timer val\n"));
883 return;
884 }
885 else if(TX_SUCCESS != tx_timer_activate(
886 &pMac->lim.limTimers.gLimRemainOnChannelTimer))
887 {
888 limLog(pMac, LOGP,
889 FL("Unable to activate remain on channel Timer\n"));
890 limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER);
891 return;
892 }
893 }
894 else
895 {
896 limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
897 eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0);
898 return;
899 }
900 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700901 }
902
903
904 // Ok-- try to allocate some memory:
905 halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
906 (tANI_U16)nBytes, ( void** ) &pFrame, (void**) &pPacket);
907 if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
908 {
909 limLog( pMac, LOGE, FL("Failed to allocate %d bytes for a Probe"
910 " Request.\n"), nBytes );
911 return;
912 }
913
914 // Paranoia:
915 palZeroMemory( pMac->hHdd, pFrame, nBytes );
916
917 if (noaLen > 0)
918 {
919 // Add 2 bytes for length and Arribute field
920 v_U32_t nBytesToCopy = ((pP2PIe + origLen + 2 ) -
921 (v_U8_t *)pMbMsg->data);
922 palCopyMemory( pMac->hHdd, pFrame, pMbMsg->data, nBytesToCopy);
923 palCopyMemory( pMac->hHdd, (pFrame + nBytesToCopy), noaStream, noaLen);
924 palCopyMemory( pMac->hHdd, (pFrame + nBytesToCopy + noaLen),
925 pMbMsg->data + nBytesToCopy, nBytes - nBytesToCopy - noaLen);
926
927 }
928 else
929 {
930 palCopyMemory(pMac->hHdd, pFrame, pMbMsg->data, nBytes);
931 }
932
933 /* Use BD rate 2 for all P2P related frames. As these frames need to go
934 * at OFDM rates. And BD rate2 we configured at 6Mbps.
935 */
936 txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
937
Jeff Johnsone7245742012-09-05 17:12:55 -0700938 if ( (SIR_MAC_MGMT_PROBE_RSP == pFc->subType) ||
939 (pMbMsg->noack)
940 )
Jeff Johnson295189b2012-06-20 16:38:30 -0700941 {
942 halstatus = halTxFrame( pMac, pPacket, (tANI_U16)nBytes,
943 HAL_TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
944 7,/*SMAC_SWBD_TX_TID_MGMT_HIGH */ limTxComplete, pFrame,
945 txFlag );
946
Jeff Johnsone7245742012-09-05 17:12:55 -0700947 if (!pMbMsg->noack)
948 {
949 limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
Jeff Johnson295189b2012-06-20 16:38:30 -0700950 halstatus, pMbMsg->sessionId, 0);
Jeff Johnsone7245742012-09-05 17:12:55 -0700951 }
952 pMac->lim.actionFrameSessionId = 0xff;
Jeff Johnson295189b2012-06-20 16:38:30 -0700953 }
954 else
955 {
956 halstatus = halTxFrameWithTxComplete( pMac, pPacket, (tANI_U16)nBytes,
957 HAL_TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
958 7,/*SMAC_SWBD_TX_TID_MGMT_HIGH */ limTxComplete, pFrame,
959 limP2PActionCnf, txFlag );
960
961 if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
962 {
963 limLog( pMac, LOGE, FL("could not send action frame!\n" ));
964 limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, halstatus,
965 pMbMsg->sessionId, 0);
Jeff Johnsone7245742012-09-05 17:12:55 -0700966 pMac->lim.actionFrameSessionId = 0xff;
Jeff Johnson295189b2012-06-20 16:38:30 -0700967 }
968 else
969 {
970 pMac->lim.actionFrameSessionId = pMbMsg->sessionId;
Jeff Johnsone7245742012-09-05 17:12:55 -0700971 limLog( pMac, LOGE, FL("lim.actionFrameSessionId = %lu\n" ),
972 pMac->lim.actionFrameSessionId);
973
Jeff Johnson295189b2012-06-20 16:38:30 -0700974 }
975 }
976
977 return;
978}
979
980
981void limAbortRemainOnChan(tpAniSirGlobal pMac)
982{
983 if(VOS_TRUE == tx_timer_running(
984 &pMac->lim.limTimers.gLimRemainOnChannelTimer))
985 {
986 //TODO check for state and take appropriate actions
987 limDeactivateAndChangeTimer(pMac, eLIM_REMAIN_CHN_TIMER);
988 limProcessRemainOnChnTimeout(pMac);
989 }
990 return;
991}
992
993/* Power Save Related Functions */
994tSirRetStatus __limProcessSmeNoAUpdate(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
995{
996 tpP2pPsConfig pNoA;
997 tpP2pPsParams pMsgNoA;
998 tSirMsgQ msg;
999
1000 pNoA = (tpP2pPsConfig) pMsgBuf;
1001
1002 if( eHAL_STATUS_SUCCESS != palAllocateMemory(
1003 pMac->hHdd, (void **) &pMsgNoA, sizeof( tP2pPsConfig )))
1004 {
1005 limLog( pMac, LOGE,
1006 FL( "Unable to allocate memory during NoA Update\n" ));
1007 return eSIR_MEM_ALLOC_FAILED;
1008 }
1009
1010 palZeroMemory( pMac->hHdd, (tANI_U8 *)pMsgNoA, sizeof(tP2pPsConfig));
1011 pMsgNoA->opp_ps = pNoA->opp_ps;
1012 pMsgNoA->ctWindow = pNoA->ctWindow;
1013 pMsgNoA->duration = pNoA->duration;
1014 pMsgNoA->interval = pNoA->interval;
1015 pMsgNoA->count = pNoA->count;
1016 pMsgNoA->single_noa_duration = pNoA->single_noa_duration;
1017 pMsgNoA->psSelection = pNoA->psSelection;
1018
1019 msg.type = SIR_HAL_SET_P2P_GO_NOA_REQ;
1020 msg.reserved = 0;
1021 msg.bodyptr = pMsgNoA;
1022 msg.bodyval = 0;
1023
1024 if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
1025 {
1026 limLog(pMac, LOGE, FL("halPostMsgApi failed\n"));
1027 return eSIR_FAILURE;
1028 }
1029
1030 return eSIR_SUCCESS;
1031} /*** end __limProcessSmeGoNegReq() ***/
1032
1033#endif
1034