blob: 50f9a54052326d6074d6d59a053ea5ab014b65a0 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
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.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**========================================================================
29
30 \file wlan_hdd_p2p.c
31
32 \brief WLAN Host Device Driver implementation for P2P commands interface
33
34 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
35
36 Qualcomm Confidential and Proprietary.
37
38 ========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070039
40#include <wlan_hdd_includes.h>
41#include <wlan_hdd_hostapd.h>
42#include <net/cfg80211.h>
43#include "sme_Api.h"
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -070044#include "sme_QosApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070045#include "wlan_hdd_p2p.h"
46#include "sapApi.h"
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053047#include "wlan_hdd_main.h"
Daram Sudha1f7e0e92013-12-17 07:52:31 +053048#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070049#include <linux/netdevice.h>
50#include <linux/skbuff.h>
51#include <linux/etherdevice.h>
52#include <net/ieee80211_radiotap.h>
Hoonki Lee1090c6a2013-01-16 17:40:54 -080053#ifdef FEATURE_WLAN_TDLS
54#include "wlan_hdd_tdls.h"
55#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053056#include "wlan_hdd_trace.h"
57#include "vos_types.h"
58#include "vos_trace.h"
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +053059#include "vos_sched.h"
60
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080061//Ms to Micro Sec
62#define MS_TO_MUS(x) ((x)*1000);
Daram Sudha1f7e0e92013-12-17 07:52:31 +053063tANI_U8* hdd_getActionString( tANI_U16 MsgType )
64{
65 switch (MsgType)
66 {
67 CASE_RETURN_STRING(SIR_MAC_ACTION_SPECTRUM_MGMT);
68 CASE_RETURN_STRING(SIR_MAC_ACTION_QOS_MGMT);
69 CASE_RETURN_STRING(SIR_MAC_ACTION_DLP);
70 CASE_RETURN_STRING(SIR_MAC_ACTION_BLKACK);
71 CASE_RETURN_STRING(SIR_MAC_ACTION_PUBLIC_USAGE);
72 CASE_RETURN_STRING(SIR_MAC_ACTION_RRM);
73 CASE_RETURN_STRING(SIR_MAC_ACTION_FAST_BSS_TRNST);
74 CASE_RETURN_STRING(SIR_MAC_ACTION_HT);
75 CASE_RETURN_STRING(SIR_MAC_ACTION_SA_QUERY);
76 CASE_RETURN_STRING(SIR_MAC_ACTION_PROT_DUAL_PUB);
77 CASE_RETURN_STRING(SIR_MAC_ACTION_WNM);
78 CASE_RETURN_STRING(SIR_MAC_ACTION_UNPROT_WNM);
79 CASE_RETURN_STRING(SIR_MAC_ACTION_TDLS);
80 CASE_RETURN_STRING(SIR_MAC_ACITON_MESH);
81 CASE_RETURN_STRING(SIR_MAC_ACTION_MULTIHOP);
82 CASE_RETURN_STRING(SIR_MAC_SELF_PROTECTED);
83 CASE_RETURN_STRING(SIR_MAC_ACTION_WME);
84 CASE_RETURN_STRING(SIR_MAC_ACTION_VHT);
85 default:
86 return ("UNKNOWN");
87 }
88}
89
90
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070091#ifdef WLAN_FEATURE_P2P_DEBUG
92#define MAX_P2P_ACTION_FRAME_TYPE 9
93const char *p2p_action_frame_type[]={"GO Negotiation Request",
94 "GO Negotiation Response",
95 "GO Negotiation Confirmation",
96 "P2P Invitation Request",
97 "P2P Invitation Response",
98 "Device Discoverability Request",
99 "Device Discoverability Response",
100 "Provision Discovery Request",
101 "Provision Discovery Response"};
102
103/* We no need to protect this variable since
104 * there is no chance of race to condition
105 * and also not make any complicating the code
106 * just for debugging log
107 */
108tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
109
110#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800111#ifdef WLAN_FEATURE_TDLS_DEBUG
112#define MAX_TDLS_ACTION_FRAME_TYPE 11
113const char *tdls_action_frame_type[] = {"TDLS Setup Request",
114 "TDLS Setup Response",
115 "TDLS Setup Confirm",
116 "TDLS Teardown",
117 "TDLS Peer Traffic Indication",
118 "TDLS Channel Switch Request",
119 "TDLS Channel Switch Response",
120 "TDLS Peer PSM Request",
121 "TDLS Peer PSM Response",
122 "TDLS Peer Traffic Response",
123 "TDLS Discovery Request" };
124#endif
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700125
Jeff Johnson295189b2012-06-20 16:38:30 -0700126extern struct net_device_ops net_ops_struct;
127
128static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
129 int rtap_len, int flag );
130
131static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
132 hdd_cfg80211_state_t* cfgState,
133 tANI_BOOLEAN actionSendSuccess );
134
135static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Rashmi Ramannac7744532013-10-06 16:49:08 +0530136 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -0700137 tANI_U8* pbFrames,
138 tANI_U8 frameType );
vamsi9bd92b72013-12-26 14:11:29 +0530139
140static v_BOOL_t hdd_p2p_is_action_type_rsp( const u8 *buf )
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530141{
vamsi9bd92b72013-12-26 14:11:29 +0530142 tActionFrmType actionFrmType;
143 const u8 *ouiPtr;
144
145 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
146 WLAN_HDD_PUBLIC_ACTION_FRAME ) {
147 return VOS_FALSE;
148 }
149
150 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] !=
151 WLAN_HDD_VENDOR_SPECIFIC_ACTION ) {
152 return VOS_FALSE;
153 }
154
155 ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET];
156
157 if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) {
158 return VOS_FALSE;
159 }
160
161 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] !=
162 WLAN_HDD_WFA_P2P_OUI_TYPE ) {
163 return VOS_FALSE;
164 }
165
Ahmad Kholaife5ec2cd2014-03-19 13:22:04 +0530166 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
vamsi9bd92b72013-12-26 14:11:29 +0530167 if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
168 actionFrmType != WLAN_HDD_GO_NEG_REQ &&
169 actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
170 actionFrmType != WLAN_HDD_PROV_DIS_REQ )
171 return VOS_TRUE;
172 else
173 return VOS_FALSE;
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530174}
Jeff Johnson295189b2012-06-20 16:38:30 -0700175
Jeff Johnson295189b2012-06-20 16:38:30 -0700176eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
177 eHalStatus status )
178{
179 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700180 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
181 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530182 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700183
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530184 if (pHddCtx == NULL)
185 {
186 hddLog(LOGE, "%s: Hdd Context is NULL", __func__);
187 return eHAL_STATUS_FAILURE;
188 }
189 if (pRemainChanCtx == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700190 {
191 hddLog( LOGW,
192 "%s: No Rem on channel pending for which Rsp is received", __func__);
193 return eHAL_STATUS_SUCCESS;
194 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530195
196 mutex_lock(&pHddCtx->roc_lock);
Rashmi Ramannac7744532013-10-06 16:49:08 +0530197 hddLog( VOS_TRACE_LEVEL_INFO,
198 "Received ROC rsp (request type %d, channel %d, cookie %llu",
199 pRemainChanCtx->rem_on_chan_request,
200 pRemainChanCtx->chan.center_freq,
201 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700202 cfgState->remain_on_chan_ctx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530203 vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
204 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530205 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530206 if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
Jeff Johnson295189b2012-06-20 16:38:30 -0700207 {
208 if( cfgState->buf )
209 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530210 hddLog( LOGP,
Jeff Johnson295189b2012-06-20 16:38:30 -0700211 "%s: We need to receive yet an ack from one of tx packet",
212 __func__);
213 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800214 cfg80211_remain_on_channel_expired(
215#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
216 pRemainChanCtx->dev->ieee80211_ptr,
217#else
218 pRemainChanCtx->dev,
219#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700220 pRemainChanCtx->cookie,
221 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700222#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
223 pRemainChanCtx->chan_type,
224#endif
225 GFP_KERNEL);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530226 pAdapter->lastRocTs = vos_timer_get_system_time();
Jeff Johnson295189b2012-06-20 16:38:30 -0700227 }
228
Jeff Johnson295189b2012-06-20 16:38:30 -0700229
230 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700231 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
232 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700233 )
234 {
235 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800236 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
237 {
238 sme_DeregisterMgmtFrame(
239 hHal, sessionId,
240 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
241 NULL, 0 );
242 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700243 }
244 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
245 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
246 )
247 {
248 WLANSAP_DeRegisterMgmtFrame(
249 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
250 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
251 NULL, 0 );
252 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530253 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
254 && pRemainChanCtx->action_pkt_buff.frame_length != 0)
255 {
256 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
257 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800258 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800259 pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700260 complete(&pAdapter->cancel_rem_on_chan_var);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530261 pAdapter->is_roc_inprogress = FALSE;
262 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 return eHAL_STATUS_SUCCESS;
264}
265
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530266VOS_STATUS wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700267{
Jeff Johnson295189b2012-06-20 16:38:30 -0700268 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530269 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530270 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700271 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700272
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530273 if (NULL == pHddCtx)
274 {
275 hddLog(LOGE, "%s: HddCtx is NULL", __func__);
276 return VOS_STATUS_E_FAILURE;
277 }
278
279 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700280 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700281 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530282 if(VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
283 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
284 {
285 hddLog(VOS_TRACE_LEVEL_INFO,
286 "Cancel Existing ROC (cookie=%llu)",
287 cfgState->remain_on_chan_ctx->cookie);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700288
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530289 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
290 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530291 /* Wait till remain on channel ready indication before issuing cancel
292 * remain on channel request, otherwise if remain on channel not
293 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700294 * will be in unknown state.
295 */
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530296 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress != TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700297 {
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530298 status = wait_for_completion_interruptible_timeout(
299 &pAdapter->rem_on_chan_ready_event,
300 msecs_to_jiffies(WAIT_REM_CHAN_READY));
301 if (0 >= status)
302 {
303 hddLog( LOGE,
304 "%s: timeout waiting for remain on channel"
305 " ready indication %d",
306 __func__, status);
307 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
308 mutex_unlock(&pHddCtx->roc_lock);
309 return VOS_STATUS_E_FAILURE;
310 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700311
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530312 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
313 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
Mahesh A Saptasgar3f692752014-11-17 16:13:35 +0530314 mutex_unlock(&pHddCtx->roc_lock);
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530315
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530316 /* Issue abort remain on chan request to sme.
317 * The remain on channel callback will make sure the remain_on_chan
318 * expired event is sent.
319 */
320 if (( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
321 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
322 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ))
323 {
324 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
Jeff Johnson295189b2012-06-20 16:38:30 -0700325 pAdapter->sessionId );
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530326 }
327 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
328 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
329 {
330 WLANSAP_CancelRemainOnChannel(
331 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
332 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700333
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530334 status = wait_for_completion_interruptible_timeout(
335 &pAdapter->cancel_rem_on_chan_var,
336 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
337 if (0 >= status)
338 {
339 hddLog( LOGE,
340 "%s: timeout waiting for cancel remain on channel"
341 " ready indication %d",
342 __func__, status);
343 }
344 hdd_allow_suspend();
345 }
346 else
347 {
348 hddLog( LOG1,
349 "ROC timer cancellation in progress,"
350 " wait for completion");
351 mutex_unlock(&pHddCtx->roc_lock);
352 status = wait_for_completion_interruptible_timeout(
353 &pAdapter->cancel_rem_on_chan_var,
354 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
355 if (0 >= status)
356 {
357 hddLog( LOGE,
358 "%s:wait on cancel_rem_on_chan_var failed %d",
359 __func__, status);
360 return VOS_STATUS_E_FAILURE;
361 }
362 return VOS_STATUS_SUCCESS;
363 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700364 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530365 else
366 {
367 hddLog(LOG1,
368 "%s: remain_on_chan_ctx is NULL", __func__);
369 mutex_unlock(&pHddCtx->roc_lock);
370 }
371 return VOS_STATUS_SUCCESS;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700372}
373
374int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
375{
376 int status = 0;
377 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
378
379 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
380 {
381 //Cancel Existing Remain On Channel
382 //If no action frame is pending
383 if( cfgState->remain_on_chan_ctx != NULL)
384 {
385 //Check whether Action Frame is pending or not
386 if( cfgState->buf == NULL)
387 {
388 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
389 }
390 else
391 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530392 hddLog(VOS_TRACE_LEVEL_DEBUG,
393 "Cannot Cancel Existing Remain on Channel");
Jeff Johnson32d95a32012-09-10 13:15:23 -0700394 status = -EBUSY;
395 }
396 }
397 }
398 return status;
399}
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530400void wlan_hdd_remain_on_chan_timeout(void *data)
401{
402 hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
403 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
404 hdd_cfg80211_state_t *cfgState;
405 if ( NULL == pAdapter )
406 {
407 hddLog( LOGE, FL("pAdapter is NULL !!!"));
408 return;
409 }
410 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
411 pRemainChanCtx = cfgState->remain_on_chan_ctx;
412 if (NULL == pRemainChanCtx)
413 {
414 hddLog( LOGE, FL("No Remain on channel is pending"));
415 return;
416 }
417 if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
418 {
419 hddLog( LOGE, FL("Cancellation already in progress"));
420 return;
421 }
422
423 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
424 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
425 hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
426 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
427 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
428 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
429 )
430 {
431 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
432 pAdapter->sessionId );
433 }
434 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
435 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
436 )
437 {
438 WLANSAP_CancelRemainOnChannel(
439 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
440 }
441 hdd_allow_suspend();
442}
Jeff Johnson32d95a32012-09-10 13:15:23 -0700443
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530444static int wlan_hdd_p2p_start_remain_on_channel(
445 hdd_adapter_t *pAdapter)
446{
447 VOS_STATUS status = VOS_STATUS_SUCCESS;
448 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
449 hdd_adapter_t *pAdapter_temp;
450 v_BOOL_t isGoPresent = VOS_FALSE;
451 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
452 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
453 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
454 rem_on_channel_request_type_t request_type = pRemainChanCtx->rem_on_chan_request;
455
456 /* Initialize Remain on chan timer */
457 status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
458 VOS_TIMER_TYPE_SW,
459 wlan_hdd_remain_on_chan_timeout,
460 pAdapter);
461 if (status != VOS_STATUS_SUCCESS)
462 {
463 hddLog(VOS_TRACE_LEVEL_ERROR,
464 "%s: Not able to initalize remain_on_chan timer", __func__);
465 }
466 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
467 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
468 {
469 pAdapter_temp = pAdapterNode->pAdapter;
470 if (WLAN_HDD_P2P_GO == pAdapter_temp->device_mode)
471 {
472 isGoPresent = VOS_TRUE;
473 }
474 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
475 pAdapterNode = pNext;
476 }
477 hdd_prevent_suspend();
478 //call sme API to start remain on channel.
479 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
480 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
481 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
482 )
483 {
484 tANI_U8 sessionId = pAdapter->sessionId;
485 //call sme API to start remain on channel.
486 if (eHAL_STATUS_SUCCESS != sme_RemainOnChannel(
487 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
488 pRemainChanCtx->chan.hw_value, pRemainChanCtx->duration,
489 wlan_hdd_remain_on_channel_callback, pAdapter,
490 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE))
491 {
492 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
493 FL(" RemainOnChannel returned fail"));
494 cfgState->remain_on_chan_ctx = NULL;
495 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
496 vos_mem_free (pRemainChanCtx);
497 hdd_allow_suspend();
498 return -EINVAL;
499 }
500
501 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
502 {
503 if( eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame(
504 WLAN_HDD_GET_HAL_CTX(pAdapter),
505 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
506 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ))
507 {
508 hddLog(VOS_TRACE_LEVEL_ERROR, "sme_RegisterMgmtFrame returned fail");
509 }
510 }
511
512 }
513 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
514 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
515 )
516 {
517 //call sme API to start remain on channel.
518 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
519 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
520 pRemainChanCtx->chan.hw_value, pRemainChanCtx->duration,
521 wlan_hdd_remain_on_channel_callback, pAdapter ))
522
523 {
524 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
525 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
526 cfgState->remain_on_chan_ctx = NULL;
527 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
528 vos_mem_free (pRemainChanCtx);
529 hdd_allow_suspend();
530 return -EINVAL;
531 }
532
533
534 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
535 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
536 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
537 NULL, 0 ))
538 {
539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
540 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
541 WLANSAP_CancelRemainOnChannel(
542 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
543 hdd_allow_suspend();
544 return -EINVAL;
545 }
546
547 }
548
549 pAdapter->is_roc_inprogress = TRUE;
550 return 0;
551}
552
553
Jeff Johnson32d95a32012-09-10 13:15:23 -0700554static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
555 struct net_device *dev,
556 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700557#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700558 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700559#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700560 unsigned int duration, u64 *cookie,
561 rem_on_channel_request_type_t request_type )
562{
563 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
564 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
565 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530566 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530567 VOS_STATUS checkReadyInd;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530568 hdd_adapter_t *pStaAdapter;
569
Jeff Johnson32d95a32012-09-10 13:15:23 -0700570 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
571 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700572#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530573 hddLog(VOS_TRACE_LEVEL_INFO,
574 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
575 " request type %d, cookie %llu",
576 chan->hw_value, chan->center_freq, channel_type, duration,
577 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700578#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530579 hddLog(VOS_TRACE_LEVEL_INFO,
580 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
581 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
582 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700583#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700584 //Cancel existing remain On Channel if any
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530585 checkReadyInd = wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
586 if (VOS_STATUS_SUCCESS != checkReadyInd)
587 {
588 hddLog( LOGE, FL("Cancel Roc in progress"));
589 return -EBUSY;
590 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700591
Jeff Johnsone7245742012-09-05 17:12:55 -0700592 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700593 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700594 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700595 * channel requets when Load/Unload is in progress*/
Rashmi Ramannab1429032014-04-26 14:59:09 +0530596 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(((hdd_context_t *)pAdapter->pHddCtx))
Ganesh Kondabattiniaeb7b772014-08-11 20:00:36 +0530597 || hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx, VOS_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700598 {
599 hddLog( LOGE,
Rashmi Ramannab1429032014-04-26 14:59:09 +0530600 "%s: Wlan Load/Unload or Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700601 return -EBUSY;
602 }
603
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700604 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
605 {
606 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
607 "%s:LOGP in Progress. Ignore!!!", __func__);
608 return -EAGAIN;
609 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700610 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
611 if( NULL == pRemainChanCtx )
612 {
613 hddLog(VOS_TRACE_LEVEL_FATAL,
614 "%s: Not able to allocate memory for Channel context",
615 __func__);
616 return -ENOMEM;
617 }
618
619 vos_mem_copy( &pRemainChanCtx->chan, chan,
620 sizeof(struct ieee80211_channel) );
621
Yue Maf49ba872013-08-19 12:04:25 -0700622#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700623 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700624#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700625 pRemainChanCtx->duration = duration;
626 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800627 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700628 pRemainChanCtx->cookie = *cookie;
629 pRemainChanCtx->rem_on_chan_request = request_type;
630 cfgState->remain_on_chan_ctx = pRemainChanCtx;
631 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530632 pRemainChanCtx->action_pkt_buff.freq = 0;
633 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
634 pRemainChanCtx->action_pkt_buff.frame_length = 0;
635 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530636 pRemainChanCtx->is_pending_roc_cancelled = FALSE;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530637
Jeff Johnson295189b2012-06-20 16:38:30 -0700638 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
639
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530640 if (REMAIN_ON_CHANNEL_REQUEST == request_type)
Jeff Johnson295189b2012-06-20 16:38:30 -0700641 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530642 pStaAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
643 if((NULL != pStaAdapter)&&
644 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pStaAdapter)))
Sushant Kaushik298a8592014-12-09 17:34:07 +0530645 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530646 if (pAdapter->lastRocTs !=0 &&
647 ((vos_timer_get_system_time() - pAdapter->lastRocTs )
648 < pHddCtx->cfg_ini->gP2PListenDeferInterval))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530649 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530650 if (pRemainChanCtx->duration > HDD_P2P_MAX_ROC_DURATION)
651 pRemainChanCtx->duration = HDD_P2P_MAX_ROC_DURATION;
652 schedule_delayed_work(&pAdapter->roc_work,
653 msecs_to_jiffies(pHddCtx->cfg_ini->gP2PListenDeferInterval));
654 hddLog(VOS_TRACE_LEVEL_INFO, "Defer interval is %hu, pAdapter %p",
655 pHddCtx->cfg_ini->gP2PListenDeferInterval, pAdapter);
656 return 0;
Rashmi Ramannac7744532013-10-06 16:49:08 +0530657 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800658 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700659 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530660
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530661 return wlan_hdd_p2p_start_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700662}
663
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530664int __wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800665#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
666 struct wireless_dev *wdev,
667#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700668 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800669#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700670 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700671#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700672 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700673#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700674 unsigned int duration, u64 *cookie )
675{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800676#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
677 struct net_device *dev = wdev->netdev;
678#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530679 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
680
681 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
682 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
683 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Jeff Johnson295189b2012-06-20 16:38:30 -0700684 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700685 chan,
686#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
687 channel_type,
688#endif
689 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700690 REMAIN_ON_CHANNEL_REQUEST);
691}
692
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530693int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
694#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
695 struct wireless_dev *wdev,
696#else
697 struct net_device *dev,
698#endif
699 struct ieee80211_channel *chan,
700#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
701 enum nl80211_channel_type channel_type,
702#endif
703 unsigned int duration, u64 *cookie )
704{
705 int ret;
706
707 vos_ssr_protect(__func__);
708 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
709#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
710 wdev,
711#else
712 dev,
713#endif
714 chan,
715#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
716 channel_type,
717#endif
718 duration, cookie);
719 vos_ssr_unprotect(__func__);
720
721 return ret;
722}
723
724
Jeff Johnson295189b2012-06-20 16:38:30 -0700725void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
726{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530727 hdd_cfg80211_state_t *cfgState = NULL;
728 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530729 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530730 if (NULL == pAdapter)
731 {
732 hddLog(LOGE, FL("pAdapter is NULL"));
733 return;
734 }
735 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
736 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530737 hddLog( LOG1, "Ready on chan ind");
Jeff Johnson295189b2012-06-20 16:38:30 -0700738 if( pRemainChanCtx != NULL )
739 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530740 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
741 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
742 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530743 //start timer for actual duration
744 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
745 (pRemainChanCtx->duration));
746 if (VOS_STATUS_SUCCESS!=status)
747 {
748 hddLog( LOGE, FL("Remain on Channel timer start failed"));
749 }
750 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700751 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800752 cfg80211_ready_on_channel(
753#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
754 pAdapter->dev->ieee80211_ptr,
755#else
756 pAdapter->dev,
757#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800758 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700759 &pRemainChanCtx->chan,
760#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
761 pRemainChanCtx->chan_type,
762#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700763 pRemainChanCtx->duration, GFP_KERNEL );
764 }
765#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530766 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700767 {
768 complete(&pAdapter->offchannel_tx_event);
769 }
770#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530771 // Check for cached action frame
772 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
773 {
774#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
775 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
776 pRemainChanCtx->action_pkt_buff.freq, 0,
777 pRemainChanCtx->action_pkt_buff.frame_ptr,
778 pRemainChanCtx->action_pkt_buff.frame_length,
779 GFP_ATOMIC );
780#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
781 cfg80211_rx_mgmt( pAdapter->dev,
782 pRemainChanCtx->action_pkt_buff.freq, 0,
783 pRemainChanCtx->action_pkt_buff.frame_ptr,
784 pRemainChanCtx->action_pkt_buff.frame_length,
785 GFP_ATOMIC );
786#else
787 cfg80211_rx_mgmt( pAdapter->dev,
788 pRemainChanCtx->action_pkt_buff.freq,
789 pRemainChanCtx->action_pkt_buff.frame_ptr,
790 pRemainChanCtx->action_pkt_buff.frame_length,
791 GFP_ATOMIC );
792#endif //LINUX_VERSION_CODE
793 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
794 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
795 pRemainChanCtx->action_pkt_buff.frame_length = 0;
796 pRemainChanCtx->action_pkt_buff.freq = 0;
797 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
798 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530799 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
800 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700801 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530802 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
803 {
804 /* since pRemainChanCtx->is_pending_roc_cancelled is
805 * set, it means Cancel Reamain on channel command is
806 * pending because remain on channel event was not
807 * ready when cancel ROC was issued.So issue
808 * cancel ROC now.
809 */
810 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
811 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700812 }
813 else
814 {
815 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
816 }
817 return;
818}
819
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530820int __wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800821#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
822 struct wireless_dev *wdev,
823#else
824 struct net_device *dev,
825#endif
826 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700827{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800828#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
829 struct net_device *dev = wdev->netdev;
830#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700831 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700832 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530833 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530834 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
835 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530836 u64 cookie_dummy;
837 cookie_dummy = cookie << 32;
838 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
839 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
840 pAdapter->sessionId, cookie_dummy));
841 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -0700842
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530843 status = wlan_hdd_validate_context(pHddCtx);
844
845 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700846 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
848 "%s: HDD context is not valid", __func__);
849 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700850 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530851 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
852
Jeff Johnson295189b2012-06-20 16:38:30 -0700853 /* FIXME cancel currently running remain on chan.
854 * Need to check cookie and cancel accordingly
855 */
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530856 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700857 if( (cfgState->remain_on_chan_ctx == NULL) ||
858 (cfgState->remain_on_chan_ctx->cookie != cookie) )
859 {
860 hddLog( LOGE,
861 "%s: No Remain on channel pending with specified cookie value",
862 __func__);
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530863 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700864 return -EINVAL;
865 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530866 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
867 {
868 /* wait until remain on channel ready event received
869 * for already issued remain on channel request */
870 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
871 msecs_to_jiffies(WAIT_REM_CHAN_READY));
872 if (0 >= status)
873 {
874 hddLog( LOGE,
875 "%s: timeout waiting for remain on channel ready indication %d",
876 __func__, status);
877 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530878 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530879 return 0;
880
881 }
882 }
883 else
884 {
885 hddLog( LOG1, FL("Cancel ROC event is already pending, "
886 "waiting for ready on channel indication.") );
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530887 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530888 return 0;
889 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530890 if (NULL != cfgState->remain_on_chan_ctx)
891 {
892 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
893 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
894 {
895 hddLog( LOG1,
896 FL("ROC timer cancellation in progress,"
897 " wait for completion"));
898 status = wait_for_completion_interruptible_timeout(
899 &pAdapter->cancel_rem_on_chan_var,
900 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
901 if (0 >= status)
902 {
903 hddLog( LOGE,
904 "%s:wait on cancel_rem_on_chan_var failed %d",
905 __func__, status);
906 }
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530907 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530908 return 0;
909 }
910 else
911 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
912 }
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530913 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700914 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
915 /* Issue abort remain on chan request to sme.
916 * The remain on channel callback will make sure the remain_on_chan
917 * expired event is sent.
918 */
919 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700920 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
921 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700922 )
923 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530924 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700925 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
926 sessionId );
927 }
928 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
929 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
930 )
931 {
932 WLANSAP_CancelRemainOnChannel(
933 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
934 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530935 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700936 {
937 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
938 __func__, pAdapter->device_mode);
939 return -EIO;
940 }
c_hpothu7f63e882013-10-02 19:13:35 +0530941 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700942 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +0530943 if (0 >= status)
944 {
945 hddLog( LOGE,
946 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
947 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530948 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700949 return 0;
950}
951
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530952int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800953#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530954 struct wireless_dev *wdev,
955#else
956 struct net_device *dev,
957#endif
958 u64 cookie )
959{
960 int ret;
961
962 vos_ssr_protect(__func__);
963 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
964#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
965 wdev,
966#else
967 dev,
968#endif
969 cookie);
970 vos_ssr_unprotect(__func__);
971
972 return ret;
973}
974
975
976#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
977int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800978 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700979#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800980 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700981 bool channel_type_valid,
982#endif
983 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800984 const u8 *buf, size_t len, bool no_cck,
985 bool dont_wait_for_ack, u64 *cookie )
986#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530987int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700988 struct ieee80211_channel *chan, bool offchan,
989 enum nl80211_channel_type channel_type,
990 bool channel_type_valid, unsigned int wait,
991 const u8 *buf, size_t len, bool no_cck,
992 bool dont_wait_for_ack, u64 *cookie )
993#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530994int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 struct ieee80211_channel *chan, bool offchan,
996 enum nl80211_channel_type channel_type,
997 bool channel_type_valid, unsigned int wait,
998 const u8 *buf, size_t len, u64 *cookie )
999#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301000int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001001 struct ieee80211_channel *chan,
1002 enum nl80211_channel_type channel_type,
1003 bool channel_type_valid,
1004 const u8 *buf, size_t len, u64 *cookie )
1005#endif //LINUX_VERSION_CODE
1006{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001007#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1008 struct net_device *dev = wdev->netdev;
1009#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001010 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301011 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1012 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
1013 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -07001014 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
1015 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
Mukul Sharma1e5d0b72014-07-01 19:22:21 +05301016 tActionFrmType actionFrmType = WLAN_HDD_ACTION_FRM_TYPE_MAX;
Jeff Johnsone7245742012-09-05 17:12:55 -07001017 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301018 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -07001019
Jeff Johnson295189b2012-06-20 16:38:30 -07001020#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1021 hdd_adapter_t *goAdapter;
1022#endif
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301023
1024 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301025 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
1026 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301027 status = wlan_hdd_validate_context(pHddCtx);
1028
1029 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001030 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1032 "%s: HDD context is not valid", __func__);
1033 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001034 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301035
c_hpothu7f63e882013-10-02 19:13:35 +05301036 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
1037 __func__, pAdapter->device_mode, type);
1038
1039
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001040 if ((type == SIR_MAC_MGMT_FRAME) &&
1041 (subType == SIR_MAC_MGMT_ACTION) &&
1042 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
1043 {
1044 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301045#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001046 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001047 {
1048 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
1049 actionFrmType);
1050 }
1051 else
1052 {
1053 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
1054 p2p_action_frame_type[actionFrmType]);
1055 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1056 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1057 {
1058 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1059 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001060 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001061 }
1062 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1063 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1064 {
1065 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1066 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
1067 " completed state");
1068 }
1069 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001070#endif
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301071 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001072
Jeff Johnsone7245742012-09-05 17:12:55 -07001073#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1074 noack = dont_wait_for_ack;
1075#endif
1076
1077 //If the wait is coming as 0 with off channel set
1078 //then set the wait to 200 ms
1079 if (offchan && !wait)
1080 wait = ACTION_FRAME_DEFAULT_WAIT;
1081
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 //Call sme API to send out a action frame.
1083 // OR can we send it directly through data path??
1084 // After tx completion send tx status back.
1085 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1086 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1087 )
1088 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001089 if (type == SIR_MAC_MGMT_FRAME)
1090 {
1091 if (subType == SIR_MAC_MGMT_PROBE_RSP)
1092 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301093 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -07001094 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301095 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001096 goto err_rem_channel;
1097 }
1098 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
1099 (subType == SIR_MAC_MGMT_DEAUTH))
1100 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001101 /* During EAP failure or P2P Group Remove supplicant
1102 * is sending del_station command to driver. From
1103 * del_station function, Driver will send deauth frame to
1104 * p2p client. No need to send disassoc frame from here.
1105 * so Drop the frame here and send tx indication back to
1106 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -07001107 */
1108 tANI_U8 dstMac[ETH_ALEN] = {0};
1109 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07001110 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001111 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -08001112 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001113 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08001114 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001115 goto err_rem_channel;
1116 }
1117 }
1118 }
1119
1120 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001121 {
1122 if ( !noack )
1123 {
1124 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1125 __func__);
1126 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1127 }
1128 else
1129 {
1130 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1131 __func__);
1132 return -EBUSY;
1133 }
1134 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001135
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301136 if( subType == SIR_MAC_MGMT_ACTION)
1137 {
1138 hddLog( LOG1, "Action frame tx request : %s",
1139 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1140 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001141
1142#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1143 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1144
1145 //If GO adapter exists and operating on same frequency
1146 //then we will not request remain on channel
1147 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1148 == goAdapter->sessionCtx.ap.operatingChannel ) )
1149 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301150 /* if GO exist and is not off channel
1151 * wait time should be zero.
1152 */
1153 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 goto send_frame;
1155 }
1156#endif
1157
1158#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1159 if( offchan && wait)
1160 {
1161 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301162 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 // In case of P2P Client mode if we are already
1164 // on the same channel then send the frame directly
1165
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301166 if( (cfgState->remain_on_chan_ctx != NULL) &&
1167 (cfgState->current_freq == chan->center_freq)
1168 )
1169 {
1170 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1171 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301172 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301173 /* Some times FW is taking almost 500 msec for
1174 * full 15 retries, which leads to ROC expiration
1175 * by the time peer gets response from other peer.
1176 * Therefore as part of temporary fix , in host
1177 * ROC time is extended. For frames where we are
1178 * expecting response from peer , its extended by
1179 * 500 msec to make ROC wait time as 1 sec and
1180 * in other cases its extended by 300 msec to make
1181 * total ROC wait as 500 msec.
1182 * TODO: FW needs to fix as why 15 retry is taking
1183 * such long time.
1184 */
1185 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1186 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1187 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1188 wait = wait + ACTION_FRAME_RSP_WAIT;
1189 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1190 actionFrmType == WLAN_HDD_INVITATION_RESP )
1191 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301192 vos_timer_stop(
1193 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1194 status = vos_timer_start(
1195 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1196 wait);
1197 if ( status != VOS_STATUS_SUCCESS )
vamsida0e5ab2013-12-26 14:33:27 +05301198 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301199 hddLog( LOGE, "Remain on Channel timer start failed");
1200 }
1201
1202 hddLog(VOS_TRACE_LEVEL_INFO,
1203 "action frame: extending the wait time %u",
1204 wait);
1205 goto send_frame;
1206 }
1207 else
1208 {
1209 if ( TRUE ==
1210 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1211 {
1212 hddLog(VOS_TRACE_LEVEL_INFO,
1213 "action frame tx: waiting for completion of ROC ");
1214
1215 status = wait_for_completion_interruptible_timeout(
1216 &pAdapter->cancel_rem_on_chan_var,
1217 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1218 if (0 >= status)
1219 {
1220 hddLog( LOGE,
1221 "%s:wait on cancel_rem_on_chan_var failed %d",
1222 __func__, status);
1223 }
vamsida0e5ab2013-12-26 14:33:27 +05301224 }
1225 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301226 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301227 hddLog(VOS_TRACE_LEVEL_INFO,
1228 "action frame: Request ROC for wait time %u", wait);
1229
Jeff Johnson295189b2012-06-20 16:38:30 -07001230 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001231 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001232 chan,
1233#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1234 channel_type,
1235#endif
1236 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301237 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001238
1239 if(0 != status)
1240 {
1241 if( (-EBUSY == status) &&
1242 (cfgState->current_freq == chan->center_freq) )
1243 {
1244 goto send_frame;
1245 }
1246 goto err_rem_channel;
1247 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001248 /* Wait for driver to be ready on the requested channel */
1249 status = wait_for_completion_interruptible_timeout(
1250 &pAdapter->offchannel_tx_event,
1251 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301252 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001253 {
c_hpothu7f63e882013-10-02 19:13:35 +05301254 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001255 goto err_rem_channel;
1256 }
1257 }
1258 else if ( offchan )
1259 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001260 /* Check before sending action frame
1261 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001262 if(NULL == cfgState->remain_on_chan_ctx)
1263 {
1264 goto err_rem_channel;
1265 }
1266 }
1267 send_frame:
1268#endif
1269
Jeff Johnsone7245742012-09-05 17:12:55 -07001270 if(!noack)
1271 {
1272 cfgState->buf = vos_mem_malloc( len ); //buf;
1273 if( cfgState->buf == NULL )
1274 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001275
Jeff Johnsone7245742012-09-05 17:12:55 -07001276 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001277
Jeff Johnsone7245742012-09-05 17:12:55 -07001278 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001279
1280#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001281 if( cfgState->remain_on_chan_ctx )
1282 {
1283 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1284 *cookie = cfgState->action_cookie;
1285 }
1286 else
1287 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001288#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001289 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001290 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001291#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001292 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001293#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301294 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001295
1296 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001297 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1298 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001299 )
1300 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001301 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001302
Jeff Johnsone7245742012-09-05 17:12:55 -07001303 if ((type == SIR_MAC_MGMT_FRAME) &&
1304 (subType == SIR_MAC_MGMT_ACTION) &&
1305 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001306 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001307 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301308 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001309 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001310 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001311 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301312 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001313 }
1314 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1315 {
1316 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301317 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001318 }
1319 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301320
Jeff Johnson295189b2012-06-20 16:38:30 -07001321 if (eHAL_STATUS_SUCCESS !=
1322 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301323 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001324 {
1325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1326 "%s: sme_sendAction returned fail", __func__);
1327 goto err;
1328 }
1329 }
1330 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1331 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1332 )
1333 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001334 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001335 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001336 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001337 {
1338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1339 "%s: WLANSAP_SendAction returned fail", __func__);
1340 goto err;
1341 }
1342 }
1343
1344 return 0;
1345err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001346 if(!noack)
1347 {
1348 hdd_sendActionCnf( pAdapter, FALSE );
1349 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001350 return 0;
1351err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001352 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001353 cfg80211_mgmt_tx_status(
1354#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1355 pAdapter->dev->ieee80211_ptr,
1356#else
1357 pAdapter->dev,
1358#endif
1359 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001360 return 0;
1361}
1362
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301363#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1364int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
1365 struct ieee80211_channel *chan, bool offchan,
1366#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1367 enum nl80211_channel_type channel_type,
1368 bool channel_type_valid,
1369#endif
1370 unsigned int wait,
1371 const u8 *buf, size_t len, bool no_cck,
1372 bool dont_wait_for_ack, u64 *cookie )
1373#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1374int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1375 struct ieee80211_channel *chan, bool offchan,
1376 enum nl80211_channel_type channel_type,
1377 bool channel_type_valid, unsigned int wait,
1378 const u8 *buf, size_t len, bool no_cck,
1379 bool dont_wait_for_ack, u64 *cookie )
1380#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1381int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1382 struct ieee80211_channel *chan, bool offchan,
1383 enum nl80211_channel_type channel_type,
1384 bool channel_type_valid, unsigned int wait,
1385 const u8 *buf, size_t len, u64 *cookie )
1386#else
1387int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1388 struct ieee80211_channel *chan,
1389 enum nl80211_channel_type channel_type,
1390 bool channel_type_valid,
1391 const u8 *buf, size_t len, u64 *cookie )
1392#endif //LINUX_VERSION_CODE
1393{
1394 int ret;
1395
1396 vos_ssr_protect(__func__);
1397#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1398 ret = __wlan_hdd_mgmt_tx(wiphy, wdev,
1399 chan, offchan,
1400#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1401 channel_type,
1402 channel_type_valid,
1403#endif
1404 wait,
1405 buf, len, no_cck,
1406 dont_wait_for_ack, cookie);
1407#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1408 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1409 channel_type, channel_type_valid, wait,
1410 buf, len, no_cck,
1411 dont_wait_for_ack, cookie);
1412#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1413 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1414 channel_type, channel_type_valid, wait,
1415 buf, len, cookie);
1416#else
1417 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, channel_type,
1418 channel_type_valid, buf, len, cookie);
1419#endif //LINUX_VERSION_CODE
1420 vos_ssr_unprotect(__func__);
1421
1422 return ret;
1423}
1424
Jeff Johnson295189b2012-06-20 16:38:30 -07001425#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001426#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301427int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001428 struct wireless_dev *wdev,
1429 u64 cookie)
1430{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301431 u64 cookie_dummy;
1432 cookie_dummy = cookie << 32;
1433 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1434 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001435 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1436}
1437#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301438int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001439 struct net_device *dev,
1440 u64 cookie)
1441{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301442 u64 cookie_dummy;
1443 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1444 cookie_dummy = cookie << 32;
1445 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1446 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1447 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001448 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1449}
1450#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001451#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001452
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301453#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1454#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1455int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1456 struct wireless_dev *wdev,
1457 u64 cookie)
1458{
1459 int ret;
1460
1461 vos_ssr_protect(__func__);
1462 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1463 vos_ssr_unprotect(__func__);
1464
1465 return ret;
1466}
1467#else
1468int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1469 struct net_device *dev,
1470 u64 cookie)
1471{
1472 int ret;
1473
1474 vos_ssr_protect(__func__);
1475 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie);
1476 vos_ssr_unprotect(__func__);
1477
1478 return ret;
1479}
1480#endif
1481#endif
1482
Jeff Johnson295189b2012-06-20 16:38:30 -07001483void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1484{
1485 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1486
Jeff Johnsone7245742012-09-05 17:12:55 -07001487 cfgState->actionFrmState = HDD_IDLE;
1488
Jeff Johnson295189b2012-06-20 16:38:30 -07001489 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1490 if( NULL == cfgState->buf )
1491 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001492 return;
1493 }
1494
1495 /* If skb is NULL it means this packet was received on CFG80211 interface
1496 * else it was received on Monitor interface */
1497 if( cfgState->skb == NULL )
1498 {
1499 /*
1500 * buf is the same pointer it passed us to send. Since we are sending
1501 * it through control path, we use different buffers.
1502 * In case of mac80211, they just push it to the skb and pass the same
1503 * data while sending tx ack status.
1504 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001505 cfg80211_mgmt_tx_status(
1506#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1507 pAdapter->dev->ieee80211_ptr,
1508#else
1509 pAdapter->dev,
1510#endif
1511 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001512 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1513 vos_mem_free( cfgState->buf );
1514 cfgState->buf = NULL;
1515 }
1516 else
1517 {
1518 hdd_adapter_t* pMonAdapter =
1519 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1520 if( pMonAdapter == NULL )
1521 {
1522 hddLog( LOGE, "Not able to get Monitor Adapter");
1523 cfgState->skb = NULL;
1524 vos_mem_free( cfgState->buf );
1525 cfgState->buf = NULL;
1526 complete(&pAdapter->tx_action_cnf_event);
1527 return;
1528 }
1529 /* Send TX completion feedback over monitor interface. */
1530 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1531 cfgState->skb = NULL;
1532 vos_mem_free( cfgState->buf );
1533 cfgState->buf = NULL;
1534 /* Look for the next Mgmt packet to TX */
1535 hdd_mon_tx_mgmt_pkt(pAdapter);
1536 }
1537 complete(&pAdapter->tx_action_cnf_event);
1538}
1539
1540/**
1541 * hdd_setP2pNoa
1542 *
1543 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301544 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001545 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1546 *
1547 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301548 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001549 *
1550 *ASSUMPTIONS:
1551 *
1552 *
1553 *NOTE:
1554 *
1555 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301556 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001557 *
1558 * @return Status
1559 */
1560
1561int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1562{
1563 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1564 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1565 VOS_STATUS status = VOS_STATUS_SUCCESS;
1566 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001567 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001568 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001569 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001570
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001571 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001572 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301573 {
1574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1575 "%s: strnchr failed to find delimeter",__func__);
1576 return -EINVAL;
1577 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001578 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001579 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1580 if (ret < 3)
1581 {
1582 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1583 "%s: P2P_SET GO NoA: fail to read param "
1584 "count=%d duration=%d interval=%d \n",
1585 __func__, count, start_time, duration);
1586 return -EINVAL;
1587 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001589 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001590 __func__, count, start_time, duration);
1591 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 /* PS Selection
1593 * Periodic NoA (2)
1594 * Single NOA (4)
1595 */
1596 NoA.opp_ps = 0;
1597 NoA.ctWindow = 0;
1598 if (count == 1)
1599 {
1600 NoA.duration = 0;
1601 NoA.single_noa_duration = duration;
1602 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1603 }
1604 else
1605 {
1606 NoA.duration = duration;
1607 NoA.single_noa_duration = 0;
1608 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1609 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001610 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001611 NoA.count = count;
1612 NoA.sessionid = pAdapter->sessionId;
1613
1614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1615 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1616 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001617 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001618 NoA.ctWindow, NoA.duration, NoA.interval,
1619 NoA.count, NoA.single_noa_duration,
1620 NoA.psSelection);
1621
1622 sme_p2pSetPs(hHal, &NoA);
1623 return status;
1624}
1625
1626/**
1627 * hdd_setP2pOpps
1628 *
1629 *FUNCTION:
1630 * This function is called from hdd_hostapd_ioctl function when Driver
1631 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1632 *
1633 *LOGIC:
1634 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1635 *
1636 *ASSUMPTIONS:
1637 *
1638 *
1639 *NOTE:
1640 *
1641 * @param dev Pointer to net device structure
1642 * @param command Pointer to command
1643 *
1644 * @return Status
1645 */
1646
1647int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1648{
1649 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1650 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1651 VOS_STATUS status = VOS_STATUS_SUCCESS;
1652 tP2pPsConfig NoA;
1653 char *param;
1654 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001655 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001656
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001657 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001658 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301659 {
1660 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1661 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001662 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301663 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001664 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001665 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1666 if (ret < 3)
1667 {
1668 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1669 "%s: P2P_SET GO PS: fail to read param "
1670 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1671 __func__, legacy_ps, opp_ps, ctwindow);
1672 return -EINVAL;
1673 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001674 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001675 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001676 __func__, legacy_ps, opp_ps, ctwindow);
1677
1678 /* PS Selection
1679 * Opportunistic Power Save (1)
1680 */
1681
1682 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1683 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301684 * values are coming from wpa_supplicant as -1.
1685 * Example : User want to set ctWindow with 30 then wpa_cli command :
1686 * P2P_SET ctwindow 30
1687 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001688 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301689 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001690 if (ctwindow != -1)
1691 {
1692
1693 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001694 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001695 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1696
1697 if (ctwindow != pAdapter->ctw)
1698 {
1699 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301700
Jeff Johnson295189b2012-06-20 16:38:30 -07001701 if(pAdapter->ops)
1702 {
1703 NoA.opp_ps = pAdapter->ops;
1704 NoA.ctWindow = pAdapter->ctw;
1705 NoA.duration = 0;
1706 NoA.single_noa_duration = 0;
1707 NoA.interval = 0;
1708 NoA.count = 0;
1709 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1710 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301711
Jeff Johnson295189b2012-06-20 16:38:30 -07001712 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1713 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1714 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001715 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 NoA.ctWindow, NoA.duration, NoA.interval,
1717 NoA.count, NoA.single_noa_duration,
1718 NoA.psSelection);
1719
1720 sme_p2pSetPs(hHal, &NoA);
1721 }
1722 return 0;
1723 }
1724 }
1725
1726 if (opp_ps != -1)
1727 {
1728 pAdapter->ops = opp_ps;
1729
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301730 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001731 {
1732 NoA.opp_ps = opp_ps;
1733 NoA.ctWindow = pAdapter->ctw;
1734 NoA.duration = 0;
1735 NoA.single_noa_duration = 0;
1736 NoA.interval = 0;
1737 NoA.count = 0;
1738 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1739 NoA.sessionid = pAdapter->sessionId;
1740
1741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1742 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1743 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001744 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001745 NoA.ctWindow, NoA.duration, NoA.interval,
1746 NoA.count, NoA.single_noa_duration,
1747 NoA.psSelection);
1748
1749 sme_p2pSetPs(hHal, &NoA);
1750 }
1751 }
1752 return status;
1753}
1754
1755int hdd_setP2pPs( struct net_device *dev, void *msgData )
1756{
1757 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1758 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1759 VOS_STATUS status = VOS_STATUS_SUCCESS;
1760 tP2pPsConfig NoA;
1761 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1762
1763 NoA.opp_ps = pappNoA->opp_ps;
1764 NoA.ctWindow = pappNoA->ctWindow;
1765 NoA.duration = pappNoA->duration;
1766 NoA.interval = pappNoA->interval;
1767 NoA.count = pappNoA->count;
1768 NoA.single_noa_duration = pappNoA->single_noa_duration;
1769 NoA.psSelection = pappNoA->psSelection;
1770 NoA.sessionid = pAdapter->sessionId;
1771
1772 sme_p2pSetPs(hHal, &NoA);
1773 return status;
1774}
Jeff Johnson295189b2012-06-20 16:38:30 -07001775
1776static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1777{
1778 tANI_U8 sessionType;
1779
1780 switch( type )
1781 {
1782 case NL80211_IFTYPE_AP:
1783 sessionType = WLAN_HDD_SOFTAP;
1784 break;
1785 case NL80211_IFTYPE_P2P_GO:
1786 sessionType = WLAN_HDD_P2P_GO;
1787 break;
1788 case NL80211_IFTYPE_P2P_CLIENT:
1789 sessionType = WLAN_HDD_P2P_CLIENT;
1790 break;
1791 case NL80211_IFTYPE_STATION:
1792 sessionType = WLAN_HDD_INFRA_STATION;
1793 break;
1794 case NL80211_IFTYPE_MONITOR:
1795 sessionType = WLAN_HDD_MONITOR;
1796 break;
1797 default:
1798 sessionType = WLAN_HDD_INFRA_STATION;
1799 break;
1800 }
1801
1802 return sessionType;
1803}
1804
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001805#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301806struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001807 struct wiphy *wiphy, const char *name,
1808 enum nl80211_iftype type,
1809 u32 *flags, struct vif_params *params )
1810#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301811struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001812 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1813 u32 *flags, struct vif_params *params )
1814#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301815struct net_device* __wlan_hdd_add_virtual_intf(
Jeff Johnson295189b2012-06-20 16:38:30 -07001816 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1817 u32 *flags, struct vif_params *params )
1818#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301819int __wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
Jeff Johnson295189b2012-06-20 16:38:30 -07001820 enum nl80211_iftype type,
1821 u32 *flags, struct vif_params *params )
1822#endif
1823{
1824 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301825 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301826 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001827 ENTER();
1828
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301829 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1830 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301831 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1832 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1833 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001834 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001835 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001836 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05301837#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1838 return ERR_PTR(-EINVAL);
1839#else
1840 return -EAGAIN;
1841#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001842 }
1843
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001844 if (pHddCtx->isLogpInProgress)
1845 {
1846 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1847 "%s:LOGP in Progress. Ignore!!!", __func__);
1848#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301849 return ERR_PTR(-EINVAL);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001850#else
1851 return -EAGAIN;
1852#endif
1853 }
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301854
1855 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1856 pScanInfo = &pHddCtx->scan_info;
1857 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1858 (pHddCtx->scan_info.mScanPending))
1859 {
1860 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1861 eCSR_SCAN_ABORT_DEFAULT);
1862 hddLog(VOS_TRACE_LEVEL_INFO,
1863 "%s: Abort Scan while adding virtual interface",__func__);
1864 }
1865
1866 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05301867 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1868 ((NL80211_IFTYPE_P2P_GO == type) ||
1869 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001870 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001871 /* Generate the P2P Interface Address. this address must be
1872 * different from the P2P Device Address.
1873 */
1874 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1875 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301876 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001877 wlan_hdd_get_session_type(type),
1878 name, p2pDeviceAddress.bytes,
1879 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001880 }
1881 else
1882 {
1883 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1884 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1885 }
1886
1887 if( NULL == pAdapter)
1888 {
1889 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1890#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301891 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001892#else
1893 return -EINVAL;
1894#endif
1895 }
1896 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001897#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1898 return pAdapter->dev->ieee80211_ptr;
1899#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001900 return pAdapter->dev;
1901#else
1902 return 0;
1903#endif
1904}
1905
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301906#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1907struct wireless_dev* wlan_hdd_add_virtual_intf(
1908 struct wiphy *wiphy, const char *name,
1909 enum nl80211_iftype type,
1910 u32 *flags, struct vif_params *params )
1911#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1912struct wireless_dev* wlan_hdd_add_virtual_intf(
1913 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1914 u32 *flags, struct vif_params *params )
1915#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1916struct net_device* wlan_hdd_add_virtual_intf(
1917 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1918 u32 *flags, struct vif_params *params )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001919#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301920int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1921 enum nl80211_iftype type,
1922 u32 *flags, struct vif_params *params )
1923#endif
1924{
1925#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)))
1926 struct wireless_dev* wdev;
1927#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1928 struct net_device* ndev;
1929#else
1930 int ret;
1931#endif
1932 vos_ssr_protect(__func__);
1933#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1934 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1935 vos_ssr_unprotect(__func__);
1936 return wdev;
1937#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1938 ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1939 vos_ssr_unprotect(__func__);
1940 return ndev;
1941#else
1942 ret = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1943 vos_ssr_unprotect(__func__);
1944 return ret;
1945#endif
1946}
1947
1948#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1949int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1950#else
1951int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001952#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001953{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001954#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1955 struct net_device *dev = wdev->netdev;
1956#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301957 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301958 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301959 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1960 int status;
1961 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001962
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301963 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1964 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1965 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301966 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1967 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001968
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301969 status = wlan_hdd_validate_context(pHddCtx);
1970
1971 if (0 != status)
1972 {
1973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1974 "%s: HDD context is not valid", __func__);
1975 return status;
1976 }
1977
1978 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001979 pVirtAdapter->macAddressCurrent.bytes );
1980
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05301981 hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301982 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1983 EXIT();
1984 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001985}
1986
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301987#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1988int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1989#else
1990int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
1991#endif
1992{
1993 int ret;
1994
1995 vos_ssr_protect(__func__);
1996#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1997 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
1998#else
1999 ret = __wlan_hdd_del_virtual_intf(wiphy, dev);
2000#endif
2001 vos_ssr_unprotect(__func__);
2002
2003 return ret;
2004}
2005
Jeff Johnson295189b2012-06-20 16:38:30 -07002006void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002007 tANI_U32 nFrameLength,
2008 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302009 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07002010{
2011 //Indicate a Frame over Monitor Intf.
2012 int rxstat;
2013 struct sk_buff *skb = NULL;
2014 int needed_headroom = 0;
2015 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
2016 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002017#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002018#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2019 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
2020#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002021#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002022 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
2023
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002024 if (NULL == pbFrames)
2025 {
2026 hddLog(LOGE, FL("NULL frame pointer"));
2027 return;
2028 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002029
2030 /* room for the radiotap header based on driver features
2031 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
2032 * RX flags.
2033 * */
2034 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
2035
2036 //alloc skb here
2037 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
2038 if (unlikely(NULL == skb))
2039 {
2040 hddLog( LOGW, FL("Unable to allocate skb"));
2041 return;
2042 }
2043 skb_reserve(skb, VPKT_SIZE_BUFFER);
2044 if (unlikely(skb_headroom(skb) < nFrameLength))
2045 {
2046 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2047 "HDD [%d]: Insufficient headroom, "
2048 "head[%p], data[%p], req[%d]",
2049 __LINE__, skb->head, skb->data, nFrameLength);
2050 kfree_skb(skb);
2051 return ;
2052 }
2053 // actually push the data
2054 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
2055 /* prepend radiotap information */
2056 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
2057 {
2058 hddLog( LOGE, FL("Not Able Add Radio Tap"));
2059 //free skb
2060 kfree_skb(skb);
2061 return ;
2062 }
2063
2064 skb_reset_mac_header( skb );
2065 skb->dev = pMonAdapter->dev;
2066 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002067 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002068#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002069#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002070 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002071#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002072#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002073 rxstat = netif_rx_ni(skb);
2074 if( NET_RX_SUCCESS == rxstat )
2075 {
2076 hddLog( LOG1, FL("Success"));
2077 }
2078 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302079 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07002080
2081 return ;
2082}
2083
2084void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302085 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07002086 tANI_U8* pbFrames,
2087 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05302088 tANI_U32 rxChan,
2089 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07002090{
2091 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302092 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07002093 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002094 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07002095 tActionFrmType actionFrmType;
2096 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302097 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05302098 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302099 VOS_STATUS status;
2100 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002101
Arif Hussain6d2a3322013-11-17 19:50:10 -08002102 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002103 __func__, frameType, nFrameLength);
2104
2105 if (NULL == pAdapter)
2106 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002107 hddLog(LOGE, FL("pAdapter is NULL"));
2108 return;
2109 }
2110
2111 if (0 == nFrameLength)
2112 {
2113 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2114 return;
2115 }
2116
2117 if (NULL == pbFrames)
2118 {
2119 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002120 return;
2121 }
2122
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002123 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2124 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2125
2126 /* Get pAdapter from Destination mac address of the frame */
2127 if ((type == SIR_MAC_MGMT_FRAME) &&
2128 (subType != SIR_MAC_MGMT_PROBE_REQ))
2129 {
2130 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
2131 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
2132 if (NULL == pAdapter)
2133 {
2134 /* Under assumtion that we don't receive any action frame
2135 * with BCST as destination we dropping action frame
2136 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08002137 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
2138 MAC_ADDRESS_STR ,
2139 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
2140 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08002141 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002142 return;
2143 }
2144 }
2145
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002146
Jeff Johnson295189b2012-06-20 16:38:30 -07002147 if (NULL == pAdapter->dev)
2148 {
2149 hddLog( LOGE, FL("pAdapter->dev is NULL"));
2150 return;
2151 }
2152
2153 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2154 {
2155 hddLog( LOGE, FL("pAdapter has invalid magic"));
2156 return;
2157 }
2158
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302159 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2160 if (NULL == pHddCtx)
2161 {
2162 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
2163 return;
2164 }
2165
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002166 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2167 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07002168 {
2169 hdd_adapter_t *pMonAdapter =
2170 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
2171
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002172 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07002173 {
2174 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
2175 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
2176 pbFrames, frameType);
2177 return;
2178 }
2179 }
2180
2181 //Channel indicated may be wrong. TODO
2182 //Indicate an action frame.
2183 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
2184 {
2185 freq = ieee80211_channel_to_frequency( rxChan,
2186 IEEE80211_BAND_2GHZ);
2187 }
2188 else
2189 {
2190 freq = ieee80211_channel_to_frequency( rxChan,
2191 IEEE80211_BAND_5GHZ);
2192 }
2193
Jeff Johnsone7245742012-09-05 17:12:55 -07002194 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302195 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302196
2197 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002198 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07002199 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002200 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
2201 {
2202 // public action frame
2203 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08002204 vos_mem_compare(&pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+2], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE))
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002205 // P2P action frames
2206 {
2207 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002208 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002209#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002210 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
2211 {
2212 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
2213 actionFrmType);
2214 }
2215 else
2216 {
2217 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
2218 p2p_action_frame_type[actionFrmType]);
2219 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
2220 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2221 {
2222 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
2223 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002224 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002225 }
2226 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
2227 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
2228 {
2229 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08002230 hddLog(LOGE,"[P2P State]GO negotiation progress to "
2231 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002232 }
2233 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
2234 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2235 {
2236 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
2237 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
2238 " completed state Autonomous GO formation");
2239 }
2240 }
2241#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302242 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
2243 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
2244 {
2245 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
2246 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
2247 actionFrmType == WLAN_HDD_INVITATION_REQ ||
2248 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
2249 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
2250 {
2251 hddLog( LOG1, "Extend RoC timer on reception of"
2252 " Action Frame");
2253 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
2254 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
2255 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
2256 else
2257 extend_time = ACTION_FRAME_DEFAULT_WAIT;
2258 if (completion_done(&pAdapter->rem_on_chan_ready_event))
2259 {
2260 vos_timer_stop(
2261 &pRemainChanCtx->hdd_remain_on_chan_timer);
2262 status = vos_timer_start(
2263 &pRemainChanCtx->hdd_remain_on_chan_timer,
2264 extend_time);
2265 if (status != VOS_STATUS_SUCCESS)
2266 {
2267 hddLog( LOGE, "ROC timer start failed");
2268 }
2269 }
2270 else
2271 {
2272 // Buffer Packet
2273 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2274 {
2275 pRemainChanCtx->action_pkt_buff.frame_length =
2276 nFrameLength;
2277 pRemainChanCtx->action_pkt_buff.freq = freq;
2278 pRemainChanCtx->action_pkt_buff.frame_ptr
2279 = vos_mem_malloc(nFrameLength);
2280 vos_mem_copy(
2281 pRemainChanCtx->action_pkt_buff.frame_ptr,
2282 pbFrames, nFrameLength);
2283 hddLog( LOGE,"%s:"
2284 "Action Pkt Cached successfully !!!", __func__);
2285 }
2286 else
2287 {
2288 hddLog( LOGE,"%s:"
2289 "Frames are pending. dropping frame !!!",
2290 __func__);
2291 }
2292 return;
2293 }
2294 }
2295 }
2296 if (pRemainChanCtx != NULL &&
2297 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2298 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2299 hddLog( LOG1, "%s:"
2300 "Rcvd action frame after timer expired ", __func__);
2301
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302302 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2303 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2304 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2305 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2306 {
2307 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2308 __func__);
2309 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002310 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002311 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002312#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002313 else if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002314 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002315 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
2316#ifdef WLAN_FEATURE_TDLS_DEBUG
2317 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2318 MAC_ADDR_ARRAY(mac),rxRssi);
2319#endif
2320 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2321 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002322 }
2323#endif
2324 }
Kaushik, Sushant507a8612014-10-21 17:00:55 +05302325
2326 pScanInfo = &pHddCtx->scan_info;
2327 if ((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2328 {
2329 hddLog(LOGE,"Action frame received when Scanning is in"
2330 " progress. Abort Scan.");
2331 hdd_abort_mac_scan(pAdapter->pHddCtx,
2332 pScanInfo->sessionId,
2333 eCSR_SCAN_ABORT_DEFAULT);
2334 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002335#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002336 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2337 {
2338 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2339 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2340 {
2341 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2342 actionFrmType);
2343 }
2344 else
2345 {
2346 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2347 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002348 }
2349 }
2350#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002351 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2352 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2353 {
Kumar Anand82c009f2014-05-29 00:29:42 -07002354 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
2355 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002356 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002357 }
2358
Jeff Johnson295189b2012-06-20 16:38:30 -07002359 //Indicate Frame Over Normal Interface
2360 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2361
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002362#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2363 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2364 pbFrames, nFrameLength,
2365 GFP_ATOMIC );
2366#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002367 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2368 pbFrames, nFrameLength,
2369 GFP_ATOMIC );
2370#else
2371 cfg80211_rx_mgmt( pAdapter->dev, freq,
2372 pbFrames, nFrameLength,
2373 GFP_ATOMIC );
2374#endif //LINUX_VERSION_CODE
2375}
2376
2377/*
2378 * ieee80211_add_rx_radiotap_header - add radiotap header
2379 */
2380static int hdd_wlan_add_rx_radiotap_hdr (
2381 struct sk_buff *skb, int rtap_len, int flag )
2382{
2383 u8 rtap_temp[20] = {0};
2384 struct ieee80211_radiotap_header *rthdr;
2385 unsigned char *pos;
2386 u16 rx_flags = 0;
2387
2388 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2389
2390 /* radiotap header, set always present flags */
2391 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2392 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2393 rthdr->it_len = cpu_to_le16(rtap_len);
2394
2395 pos = (unsigned char *) (rthdr + 1);
2396
2397 /* the order of the following fields is important */
2398
2399 /* IEEE80211_RADIOTAP_FLAGS */
2400 *pos = 0;
2401 pos++;
2402
2403 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2404 /* ensure 2 byte alignment for the 2 byte field as required */
2405 if ((pos - (u8 *)rthdr) & 1)
2406 pos++;
2407 put_unaligned_le16(rx_flags, pos);
2408 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302409
Jeff Johnson295189b2012-06-20 16:38:30 -07002410 // actually push the data
2411 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2412
2413 return 0;
2414}
2415
2416static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2417 hdd_cfg80211_state_t* cfgState,
2418 tANI_BOOLEAN actionSendSuccess )
2419{
2420 struct ieee80211_radiotap_header *rthdr;
2421 unsigned char *pos;
2422 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002423#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002424#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2425 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2426#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002427#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002428
2429 /* 2 Byte for TX flags and 1 Byte for Retry count */
2430 u32 rtHdrLen = sizeof(*rthdr) + 3;
2431
2432 u8 *data;
2433
2434 /* We have to return skb with Data starting with MAC header. We have
2435 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2436 * entire skb->len from skb and then we will push cfgState->buf to skb
2437 * */
2438 if( NULL == skb_pull(skb, skb->len) )
2439 {
2440 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2441 kfree_skb(cfgState->skb);
2442 return;
2443 }
2444
2445 data = skb_push( skb, cfgState->len );
2446
2447 if (data == NULL)
2448 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002449 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002450 kfree_skb( cfgState->skb );
2451 return;
2452 }
2453
2454 memcpy( data, cfgState->buf, cfgState->len );
2455
2456 /* send frame to monitor interfaces now */
2457 if( skb_headroom(skb) < rtHdrLen )
2458 {
2459 hddLog( LOGE, FL("No headroom for rtap header"));
2460 kfree_skb(cfgState->skb);
2461 return;
2462 }
2463
2464 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2465
2466 memset( rthdr, 0, rtHdrLen );
2467 rthdr->it_len = cpu_to_le16( rtHdrLen );
2468 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2469 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2470 );
2471
2472 pos = (unsigned char *)( rthdr+1 );
2473
2474 // Fill TX flags
2475 *pos = actionSendSuccess;
2476 pos += 2;
2477
2478 // Fill retry count
2479 *pos = 0;
2480 pos++;
2481
2482 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002483 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002484 skb->pkt_type = PACKET_OTHERHOST;
2485 skb->protocol = htons(ETH_P_802_2);
2486 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002487#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002488#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002489 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002490#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002491#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002492 if (in_interrupt())
2493 netif_rx( skb );
2494 else
2495 netif_rx_ni( skb );
2496
2497 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05302498 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302499 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002500
2501}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302502
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05302503void hdd_p2p_roc_work_queue(struct work_struct *work)
2504{
2505 hdd_adapter_t *pAdapter = container_of(to_delayed_work(work), hdd_adapter_t, roc_work);
2506 hddLog( VOS_TRACE_LEVEL_INFO, FL("%s: "), __func__);
2507 wlan_hdd_p2p_start_remain_on_channel(pAdapter);
2508 return;
2509}
2510