blob: 6459b3e04c5456aeb340739fc1e2153f60ff4f2e [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))
Padma, Santhosh Kumar98f271d2014-12-31 17:23:31 +0530597 || hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx))
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
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301165 mutex_lock(&pHddCtx->roc_lock);
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);
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301205 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301206 goto send_frame;
1207 }
1208 else
1209 {
1210 if ( TRUE ==
1211 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1212 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301213 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301214 hddLog(VOS_TRACE_LEVEL_INFO,
1215 "action frame tx: waiting for completion of ROC ");
1216
1217 status = wait_for_completion_interruptible_timeout(
1218 &pAdapter->cancel_rem_on_chan_var,
1219 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1220 if (0 >= status)
1221 {
1222 hddLog( LOGE,
1223 "%s:wait on cancel_rem_on_chan_var failed %d",
1224 __func__, status);
1225 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301226 goto bypass_lock;
vamsida0e5ab2013-12-26 14:33:27 +05301227 }
1228 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301229 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301230 mutex_unlock(&pHddCtx->roc_lock);
1231bypass_lock:
Rashmi Ramannac7744532013-10-06 16:49:08 +05301232 hddLog(VOS_TRACE_LEVEL_INFO,
1233 "action frame: Request ROC for wait time %u", wait);
Jeff Johnson295189b2012-06-20 16:38:30 -07001234 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001235 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001236 chan,
1237#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1238 channel_type,
1239#endif
1240 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301241 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001242
1243 if(0 != status)
1244 {
1245 if( (-EBUSY == status) &&
1246 (cfgState->current_freq == chan->center_freq) )
1247 {
1248 goto send_frame;
1249 }
1250 goto err_rem_channel;
1251 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001252 /* Wait for driver to be ready on the requested channel */
1253 status = wait_for_completion_interruptible_timeout(
1254 &pAdapter->offchannel_tx_event,
1255 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301256 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001257 {
c_hpothu7f63e882013-10-02 19:13:35 +05301258 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001259 goto err_rem_channel;
1260 }
1261 }
1262 else if ( offchan )
1263 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001264 /* Check before sending action frame
1265 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001266 if(NULL == cfgState->remain_on_chan_ctx)
1267 {
1268 goto err_rem_channel;
1269 }
1270 }
1271 send_frame:
1272#endif
1273
Jeff Johnsone7245742012-09-05 17:12:55 -07001274 if(!noack)
1275 {
1276 cfgState->buf = vos_mem_malloc( len ); //buf;
1277 if( cfgState->buf == NULL )
1278 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001279
Jeff Johnsone7245742012-09-05 17:12:55 -07001280 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001281
Jeff Johnsone7245742012-09-05 17:12:55 -07001282 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001283
1284#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001285 if( cfgState->remain_on_chan_ctx )
1286 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301287 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07001288 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1289 *cookie = cfgState->action_cookie;
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301290 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07001291 }
1292 else
1293 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001294#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001295 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001296 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001297#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001298 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001299#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301300 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001301
1302 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001303 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1304 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001305 )
1306 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001307 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001308
Jeff Johnsone7245742012-09-05 17:12:55 -07001309 if ((type == SIR_MAC_MGMT_FRAME) &&
1310 (subType == SIR_MAC_MGMT_ACTION) &&
1311 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001312 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001313 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301314 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001315 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001316 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001317 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301318 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001319 }
1320 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1321 {
1322 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301323 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001324 }
1325 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301326
Jeff Johnson295189b2012-06-20 16:38:30 -07001327 if (eHAL_STATUS_SUCCESS !=
1328 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301329 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001330 {
1331 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1332 "%s: sme_sendAction returned fail", __func__);
1333 goto err;
1334 }
1335 }
1336 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1337 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1338 )
1339 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001340 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001341 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001342 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001343 {
1344 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1345 "%s: WLANSAP_SendAction returned fail", __func__);
1346 goto err;
1347 }
1348 }
1349
1350 return 0;
1351err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001352 if(!noack)
1353 {
1354 hdd_sendActionCnf( pAdapter, FALSE );
1355 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001356 return 0;
1357err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001358 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001359 cfg80211_mgmt_tx_status(
1360#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1361 pAdapter->dev->ieee80211_ptr,
1362#else
1363 pAdapter->dev,
1364#endif
1365 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001366 return 0;
1367}
1368
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301369#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1370int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
1371 struct ieee80211_channel *chan, bool offchan,
1372#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1373 enum nl80211_channel_type channel_type,
1374 bool channel_type_valid,
1375#endif
1376 unsigned int wait,
1377 const u8 *buf, size_t len, bool no_cck,
1378 bool dont_wait_for_ack, u64 *cookie )
1379#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1380int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1381 struct ieee80211_channel *chan, bool offchan,
1382 enum nl80211_channel_type channel_type,
1383 bool channel_type_valid, unsigned int wait,
1384 const u8 *buf, size_t len, bool no_cck,
1385 bool dont_wait_for_ack, u64 *cookie )
1386#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1387int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1388 struct ieee80211_channel *chan, bool offchan,
1389 enum nl80211_channel_type channel_type,
1390 bool channel_type_valid, unsigned int wait,
1391 const u8 *buf, size_t len, u64 *cookie )
1392#else
1393int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1394 struct ieee80211_channel *chan,
1395 enum nl80211_channel_type channel_type,
1396 bool channel_type_valid,
1397 const u8 *buf, size_t len, u64 *cookie )
1398#endif //LINUX_VERSION_CODE
1399{
1400 int ret;
1401
1402 vos_ssr_protect(__func__);
1403#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1404 ret = __wlan_hdd_mgmt_tx(wiphy, wdev,
1405 chan, offchan,
1406#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1407 channel_type,
1408 channel_type_valid,
1409#endif
1410 wait,
1411 buf, len, no_cck,
1412 dont_wait_for_ack, cookie);
1413#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1414 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1415 channel_type, channel_type_valid, wait,
1416 buf, len, no_cck,
1417 dont_wait_for_ack, cookie);
1418#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1419 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1420 channel_type, channel_type_valid, wait,
1421 buf, len, cookie);
1422#else
1423 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, channel_type,
1424 channel_type_valid, buf, len, cookie);
1425#endif //LINUX_VERSION_CODE
1426 vos_ssr_unprotect(__func__);
1427
1428 return ret;
1429}
1430
Jeff Johnson295189b2012-06-20 16:38:30 -07001431#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001432#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301433int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001434 struct wireless_dev *wdev,
1435 u64 cookie)
1436{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301437 u64 cookie_dummy;
1438 cookie_dummy = cookie << 32;
1439 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1440 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001441 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1442}
1443#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301444int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001445 struct net_device *dev,
1446 u64 cookie)
1447{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301448 u64 cookie_dummy;
1449 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1450 cookie_dummy = cookie << 32;
1451 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1452 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1453 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001454 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1455}
1456#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001457#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001458
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301459#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1460#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1461int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1462 struct wireless_dev *wdev,
1463 u64 cookie)
1464{
1465 int ret;
1466
1467 vos_ssr_protect(__func__);
1468 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1469 vos_ssr_unprotect(__func__);
1470
1471 return ret;
1472}
1473#else
1474int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1475 struct net_device *dev,
1476 u64 cookie)
1477{
1478 int ret;
1479
1480 vos_ssr_protect(__func__);
1481 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie);
1482 vos_ssr_unprotect(__func__);
1483
1484 return ret;
1485}
1486#endif
1487#endif
1488
Jeff Johnson295189b2012-06-20 16:38:30 -07001489void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1490{
1491 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1492
Jeff Johnsone7245742012-09-05 17:12:55 -07001493 cfgState->actionFrmState = HDD_IDLE;
1494
Jeff Johnson295189b2012-06-20 16:38:30 -07001495 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1496 if( NULL == cfgState->buf )
1497 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001498 return;
1499 }
1500
1501 /* If skb is NULL it means this packet was received on CFG80211 interface
1502 * else it was received on Monitor interface */
1503 if( cfgState->skb == NULL )
1504 {
1505 /*
1506 * buf is the same pointer it passed us to send. Since we are sending
1507 * it through control path, we use different buffers.
1508 * In case of mac80211, they just push it to the skb and pass the same
1509 * data while sending tx ack status.
1510 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001511 cfg80211_mgmt_tx_status(
1512#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1513 pAdapter->dev->ieee80211_ptr,
1514#else
1515 pAdapter->dev,
1516#endif
1517 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001518 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1519 vos_mem_free( cfgState->buf );
1520 cfgState->buf = NULL;
1521 }
1522 else
1523 {
1524 hdd_adapter_t* pMonAdapter =
1525 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1526 if( pMonAdapter == NULL )
1527 {
1528 hddLog( LOGE, "Not able to get Monitor Adapter");
1529 cfgState->skb = NULL;
1530 vos_mem_free( cfgState->buf );
1531 cfgState->buf = NULL;
1532 complete(&pAdapter->tx_action_cnf_event);
1533 return;
1534 }
1535 /* Send TX completion feedback over monitor interface. */
1536 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1537 cfgState->skb = NULL;
1538 vos_mem_free( cfgState->buf );
1539 cfgState->buf = NULL;
1540 /* Look for the next Mgmt packet to TX */
1541 hdd_mon_tx_mgmt_pkt(pAdapter);
1542 }
1543 complete(&pAdapter->tx_action_cnf_event);
1544}
1545
1546/**
1547 * hdd_setP2pNoa
1548 *
1549 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301550 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001551 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1552 *
1553 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301554 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001555 *
1556 *ASSUMPTIONS:
1557 *
1558 *
1559 *NOTE:
1560 *
1561 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301562 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 *
1564 * @return Status
1565 */
1566
1567int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1568{
1569 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1570 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1571 VOS_STATUS status = VOS_STATUS_SUCCESS;
1572 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001573 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001574 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001575 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001576
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001577 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001578 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301579 {
1580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1581 "%s: strnchr failed to find delimeter",__func__);
1582 return -EINVAL;
1583 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001584 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001585 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1586 if (ret < 3)
1587 {
1588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1589 "%s: P2P_SET GO NoA: fail to read param "
1590 "count=%d duration=%d interval=%d \n",
1591 __func__, count, start_time, duration);
1592 return -EINVAL;
1593 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001595 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001596 __func__, count, start_time, duration);
1597 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001598 /* PS Selection
1599 * Periodic NoA (2)
1600 * Single NOA (4)
1601 */
1602 NoA.opp_ps = 0;
1603 NoA.ctWindow = 0;
1604 if (count == 1)
1605 {
1606 NoA.duration = 0;
1607 NoA.single_noa_duration = duration;
1608 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1609 }
1610 else
1611 {
1612 NoA.duration = duration;
1613 NoA.single_noa_duration = 0;
1614 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1615 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001616 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001617 NoA.count = count;
1618 NoA.sessionid = pAdapter->sessionId;
1619
1620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1621 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1622 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001623 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001624 NoA.ctWindow, NoA.duration, NoA.interval,
1625 NoA.count, NoA.single_noa_duration,
1626 NoA.psSelection);
1627
1628 sme_p2pSetPs(hHal, &NoA);
1629 return status;
1630}
1631
1632/**
1633 * hdd_setP2pOpps
1634 *
1635 *FUNCTION:
1636 * This function is called from hdd_hostapd_ioctl function when Driver
1637 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1638 *
1639 *LOGIC:
1640 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1641 *
1642 *ASSUMPTIONS:
1643 *
1644 *
1645 *NOTE:
1646 *
1647 * @param dev Pointer to net device structure
1648 * @param command Pointer to command
1649 *
1650 * @return Status
1651 */
1652
1653int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1654{
1655 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1656 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1657 VOS_STATUS status = VOS_STATUS_SUCCESS;
1658 tP2pPsConfig NoA;
1659 char *param;
1660 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001661 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001662
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001663 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001664 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301665 {
1666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1667 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001668 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301669 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001670 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001671 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1672 if (ret < 3)
1673 {
1674 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1675 "%s: P2P_SET GO PS: fail to read param "
1676 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1677 __func__, legacy_ps, opp_ps, ctwindow);
1678 return -EINVAL;
1679 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001680 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001681 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001682 __func__, legacy_ps, opp_ps, ctwindow);
1683
1684 /* PS Selection
1685 * Opportunistic Power Save (1)
1686 */
1687
1688 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1689 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301690 * values are coming from wpa_supplicant as -1.
1691 * Example : User want to set ctWindow with 30 then wpa_cli command :
1692 * P2P_SET ctwindow 30
1693 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001694 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301695 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001696 if (ctwindow != -1)
1697 {
1698
1699 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001700 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001701 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1702
1703 if (ctwindow != pAdapter->ctw)
1704 {
1705 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301706
Jeff Johnson295189b2012-06-20 16:38:30 -07001707 if(pAdapter->ops)
1708 {
1709 NoA.opp_ps = pAdapter->ops;
1710 NoA.ctWindow = pAdapter->ctw;
1711 NoA.duration = 0;
1712 NoA.single_noa_duration = 0;
1713 NoA.interval = 0;
1714 NoA.count = 0;
1715 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1716 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301717
Jeff Johnson295189b2012-06-20 16:38:30 -07001718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1719 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1720 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001721 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001722 NoA.ctWindow, NoA.duration, NoA.interval,
1723 NoA.count, NoA.single_noa_duration,
1724 NoA.psSelection);
1725
1726 sme_p2pSetPs(hHal, &NoA);
1727 }
1728 return 0;
1729 }
1730 }
1731
1732 if (opp_ps != -1)
1733 {
1734 pAdapter->ops = opp_ps;
1735
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301736 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001737 {
1738 NoA.opp_ps = opp_ps;
1739 NoA.ctWindow = pAdapter->ctw;
1740 NoA.duration = 0;
1741 NoA.single_noa_duration = 0;
1742 NoA.interval = 0;
1743 NoA.count = 0;
1744 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1745 NoA.sessionid = pAdapter->sessionId;
1746
1747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1748 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1749 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001750 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001751 NoA.ctWindow, NoA.duration, NoA.interval,
1752 NoA.count, NoA.single_noa_duration,
1753 NoA.psSelection);
1754
1755 sme_p2pSetPs(hHal, &NoA);
1756 }
1757 }
1758 return status;
1759}
1760
1761int hdd_setP2pPs( struct net_device *dev, void *msgData )
1762{
1763 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1764 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1765 VOS_STATUS status = VOS_STATUS_SUCCESS;
1766 tP2pPsConfig NoA;
1767 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1768
1769 NoA.opp_ps = pappNoA->opp_ps;
1770 NoA.ctWindow = pappNoA->ctWindow;
1771 NoA.duration = pappNoA->duration;
1772 NoA.interval = pappNoA->interval;
1773 NoA.count = pappNoA->count;
1774 NoA.single_noa_duration = pappNoA->single_noa_duration;
1775 NoA.psSelection = pappNoA->psSelection;
1776 NoA.sessionid = pAdapter->sessionId;
1777
1778 sme_p2pSetPs(hHal, &NoA);
1779 return status;
1780}
Jeff Johnson295189b2012-06-20 16:38:30 -07001781
1782static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1783{
1784 tANI_U8 sessionType;
1785
1786 switch( type )
1787 {
1788 case NL80211_IFTYPE_AP:
1789 sessionType = WLAN_HDD_SOFTAP;
1790 break;
1791 case NL80211_IFTYPE_P2P_GO:
1792 sessionType = WLAN_HDD_P2P_GO;
1793 break;
1794 case NL80211_IFTYPE_P2P_CLIENT:
1795 sessionType = WLAN_HDD_P2P_CLIENT;
1796 break;
1797 case NL80211_IFTYPE_STATION:
1798 sessionType = WLAN_HDD_INFRA_STATION;
1799 break;
1800 case NL80211_IFTYPE_MONITOR:
1801 sessionType = WLAN_HDD_MONITOR;
1802 break;
1803 default:
1804 sessionType = WLAN_HDD_INFRA_STATION;
1805 break;
1806 }
1807
1808 return sessionType;
1809}
1810
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001811#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301812struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001813 struct wiphy *wiphy, const char *name,
1814 enum nl80211_iftype type,
1815 u32 *flags, struct vif_params *params )
1816#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301817struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001818 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1819 u32 *flags, struct vif_params *params )
1820#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301821struct net_device* __wlan_hdd_add_virtual_intf(
Jeff Johnson295189b2012-06-20 16:38:30 -07001822 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1823 u32 *flags, struct vif_params *params )
1824#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301825int __wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
Jeff Johnson295189b2012-06-20 16:38:30 -07001826 enum nl80211_iftype type,
1827 u32 *flags, struct vif_params *params )
1828#endif
1829{
1830 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301831 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301832 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001833 ENTER();
1834
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301835 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1836 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301837 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1838 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1839 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001840 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001841 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001842 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05301843#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1844 return ERR_PTR(-EINVAL);
1845#else
1846 return -EAGAIN;
1847#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001848 }
1849
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001850 if (pHddCtx->isLogpInProgress)
1851 {
1852 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1853 "%s:LOGP in Progress. Ignore!!!", __func__);
1854#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301855 return ERR_PTR(-EINVAL);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001856#else
1857 return -EAGAIN;
1858#endif
1859 }
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301860
1861 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1862 pScanInfo = &pHddCtx->scan_info;
1863 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1864 (pHddCtx->scan_info.mScanPending))
1865 {
1866 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1867 eCSR_SCAN_ABORT_DEFAULT);
1868 hddLog(VOS_TRACE_LEVEL_INFO,
1869 "%s: Abort Scan while adding virtual interface",__func__);
1870 }
1871
1872 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05301873 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1874 ((NL80211_IFTYPE_P2P_GO == type) ||
1875 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001876 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001877 /* Generate the P2P Interface Address. this address must be
1878 * different from the P2P Device Address.
1879 */
1880 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1881 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301882 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001883 wlan_hdd_get_session_type(type),
1884 name, p2pDeviceAddress.bytes,
1885 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001886 }
1887 else
1888 {
1889 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1890 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1891 }
1892
1893 if( NULL == pAdapter)
1894 {
1895 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1896#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301897 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001898#else
1899 return -EINVAL;
1900#endif
1901 }
1902 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001903#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1904 return pAdapter->dev->ieee80211_ptr;
1905#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001906 return pAdapter->dev;
1907#else
1908 return 0;
1909#endif
1910}
1911
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301912#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1913struct wireless_dev* wlan_hdd_add_virtual_intf(
1914 struct wiphy *wiphy, const char *name,
1915 enum nl80211_iftype type,
1916 u32 *flags, struct vif_params *params )
1917#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1918struct wireless_dev* wlan_hdd_add_virtual_intf(
1919 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1920 u32 *flags, struct vif_params *params )
1921#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1922struct net_device* wlan_hdd_add_virtual_intf(
1923 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1924 u32 *flags, struct vif_params *params )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001925#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301926int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1927 enum nl80211_iftype type,
1928 u32 *flags, struct vif_params *params )
1929#endif
1930{
1931#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)))
1932 struct wireless_dev* wdev;
1933#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1934 struct net_device* ndev;
1935#else
1936 int ret;
1937#endif
1938 vos_ssr_protect(__func__);
1939#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1940 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1941 vos_ssr_unprotect(__func__);
1942 return wdev;
1943#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1944 ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1945 vos_ssr_unprotect(__func__);
1946 return ndev;
1947#else
1948 ret = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1949 vos_ssr_unprotect(__func__);
1950 return ret;
1951#endif
1952}
1953
1954#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1955int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1956#else
1957int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001958#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001959{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001960#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1961 struct net_device *dev = wdev->netdev;
1962#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301963 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301964 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301965 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1966 int status;
1967 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001968
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301969 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1970 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1971 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301972 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1973 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001974
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301975 status = wlan_hdd_validate_context(pHddCtx);
1976
1977 if (0 != status)
1978 {
1979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1980 "%s: HDD context is not valid", __func__);
1981 return status;
1982 }
1983
1984 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001985 pVirtAdapter->macAddressCurrent.bytes );
1986
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05301987 hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301988 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1989 EXIT();
1990 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001991}
1992
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301993#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1994int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1995#else
1996int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
1997#endif
1998{
1999 int ret;
2000
2001 vos_ssr_protect(__func__);
2002#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2003 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
2004#else
2005 ret = __wlan_hdd_del_virtual_intf(wiphy, dev);
2006#endif
2007 vos_ssr_unprotect(__func__);
2008
2009 return ret;
2010}
2011
Jeff Johnson295189b2012-06-20 16:38:30 -07002012void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002013 tANI_U32 nFrameLength,
2014 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302015 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07002016{
2017 //Indicate a Frame over Monitor Intf.
2018 int rxstat;
2019 struct sk_buff *skb = NULL;
2020 int needed_headroom = 0;
2021 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
2022 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002023#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002024#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2025 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
2026#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002027#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002028 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
2029
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002030 if (NULL == pbFrames)
2031 {
2032 hddLog(LOGE, FL("NULL frame pointer"));
2033 return;
2034 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002035
2036 /* room for the radiotap header based on driver features
2037 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
2038 * RX flags.
2039 * */
2040 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
2041
2042 //alloc skb here
2043 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
2044 if (unlikely(NULL == skb))
2045 {
2046 hddLog( LOGW, FL("Unable to allocate skb"));
2047 return;
2048 }
2049 skb_reserve(skb, VPKT_SIZE_BUFFER);
2050 if (unlikely(skb_headroom(skb) < nFrameLength))
2051 {
2052 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2053 "HDD [%d]: Insufficient headroom, "
2054 "head[%p], data[%p], req[%d]",
2055 __LINE__, skb->head, skb->data, nFrameLength);
2056 kfree_skb(skb);
2057 return ;
2058 }
2059 // actually push the data
2060 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
2061 /* prepend radiotap information */
2062 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
2063 {
2064 hddLog( LOGE, FL("Not Able Add Radio Tap"));
2065 //free skb
2066 kfree_skb(skb);
2067 return ;
2068 }
2069
2070 skb_reset_mac_header( skb );
2071 skb->dev = pMonAdapter->dev;
2072 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002073 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002074#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002075#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002076 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002077#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002078#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002079 rxstat = netif_rx_ni(skb);
2080 if( NET_RX_SUCCESS == rxstat )
2081 {
2082 hddLog( LOG1, FL("Success"));
2083 }
2084 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302085 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07002086
2087 return ;
2088}
2089
2090void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302091 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07002092 tANI_U8* pbFrames,
2093 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05302094 tANI_U32 rxChan,
2095 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07002096{
2097 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302098 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07002099 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002100 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07002101 tActionFrmType actionFrmType;
2102 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302103 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05302104 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302105 VOS_STATUS status;
2106 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002107
Arif Hussain6d2a3322013-11-17 19:50:10 -08002108 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002109 __func__, frameType, nFrameLength);
2110
2111 if (NULL == pAdapter)
2112 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002113 hddLog(LOGE, FL("pAdapter is NULL"));
2114 return;
2115 }
2116
2117 if (0 == nFrameLength)
2118 {
2119 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2120 return;
2121 }
2122
2123 if (NULL == pbFrames)
2124 {
2125 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002126 return;
2127 }
2128
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002129 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2130 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2131
2132 /* Get pAdapter from Destination mac address of the frame */
2133 if ((type == SIR_MAC_MGMT_FRAME) &&
2134 (subType != SIR_MAC_MGMT_PROBE_REQ))
2135 {
2136 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
2137 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
2138 if (NULL == pAdapter)
2139 {
2140 /* Under assumtion that we don't receive any action frame
2141 * with BCST as destination we dropping action frame
2142 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08002143 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
2144 MAC_ADDRESS_STR ,
2145 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
2146 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08002147 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002148 return;
2149 }
2150 }
2151
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002152
Jeff Johnson295189b2012-06-20 16:38:30 -07002153 if (NULL == pAdapter->dev)
2154 {
2155 hddLog( LOGE, FL("pAdapter->dev is NULL"));
2156 return;
2157 }
2158
2159 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2160 {
2161 hddLog( LOGE, FL("pAdapter has invalid magic"));
2162 return;
2163 }
2164
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302165 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2166 if (NULL == pHddCtx)
2167 {
2168 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
2169 return;
2170 }
2171
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002172 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2173 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07002174 {
2175 hdd_adapter_t *pMonAdapter =
2176 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
2177
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002178 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07002179 {
2180 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
2181 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
2182 pbFrames, frameType);
2183 return;
2184 }
2185 }
2186
2187 //Channel indicated may be wrong. TODO
2188 //Indicate an action frame.
2189 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
2190 {
2191 freq = ieee80211_channel_to_frequency( rxChan,
2192 IEEE80211_BAND_2GHZ);
2193 }
2194 else
2195 {
2196 freq = ieee80211_channel_to_frequency( rxChan,
2197 IEEE80211_BAND_5GHZ);
2198 }
2199
Jeff Johnsone7245742012-09-05 17:12:55 -07002200 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302201 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302202
2203 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002204 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07002205 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002206 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
2207 {
2208 // public action frame
2209 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08002210 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 -08002211 // P2P action frames
2212 {
2213 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002214 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002215#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002216 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
2217 {
2218 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
2219 actionFrmType);
2220 }
2221 else
2222 {
2223 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
2224 p2p_action_frame_type[actionFrmType]);
2225 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
2226 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2227 {
2228 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
2229 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002230 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002231 }
2232 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
2233 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
2234 {
2235 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08002236 hddLog(LOGE,"[P2P State]GO negotiation progress to "
2237 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002238 }
2239 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
2240 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2241 {
2242 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
2243 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
2244 " completed state Autonomous GO formation");
2245 }
2246 }
2247#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302248 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
2249 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
2250 {
2251 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
2252 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
2253 actionFrmType == WLAN_HDD_INVITATION_REQ ||
2254 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
2255 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
2256 {
2257 hddLog( LOG1, "Extend RoC timer on reception of"
2258 " Action Frame");
2259 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
2260 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
2261 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
2262 else
2263 extend_time = ACTION_FRAME_DEFAULT_WAIT;
2264 if (completion_done(&pAdapter->rem_on_chan_ready_event))
2265 {
2266 vos_timer_stop(
2267 &pRemainChanCtx->hdd_remain_on_chan_timer);
2268 status = vos_timer_start(
2269 &pRemainChanCtx->hdd_remain_on_chan_timer,
2270 extend_time);
2271 if (status != VOS_STATUS_SUCCESS)
2272 {
2273 hddLog( LOGE, "ROC timer start failed");
2274 }
2275 }
2276 else
2277 {
2278 // Buffer Packet
2279 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2280 {
2281 pRemainChanCtx->action_pkt_buff.frame_length =
2282 nFrameLength;
2283 pRemainChanCtx->action_pkt_buff.freq = freq;
2284 pRemainChanCtx->action_pkt_buff.frame_ptr
2285 = vos_mem_malloc(nFrameLength);
2286 vos_mem_copy(
2287 pRemainChanCtx->action_pkt_buff.frame_ptr,
2288 pbFrames, nFrameLength);
2289 hddLog( LOGE,"%s:"
2290 "Action Pkt Cached successfully !!!", __func__);
2291 }
2292 else
2293 {
2294 hddLog( LOGE,"%s:"
2295 "Frames are pending. dropping frame !!!",
2296 __func__);
2297 }
2298 return;
2299 }
2300 }
2301 }
2302 if (pRemainChanCtx != NULL &&
2303 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2304 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2305 hddLog( LOG1, "%s:"
2306 "Rcvd action frame after timer expired ", __func__);
2307
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302308 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2309 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2310 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2311 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2312 {
2313 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2314 __func__);
2315 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002316 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002317 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002318#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002319 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 -07002320 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002321 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
2322#ifdef WLAN_FEATURE_TDLS_DEBUG
2323 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2324 MAC_ADDR_ARRAY(mac),rxRssi);
2325#endif
2326 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2327 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002328 }
2329#endif
2330 }
Kaushik, Sushant507a8612014-10-21 17:00:55 +05302331
2332 pScanInfo = &pHddCtx->scan_info;
2333 if ((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2334 {
2335 hddLog(LOGE,"Action frame received when Scanning is in"
2336 " progress. Abort Scan.");
2337 hdd_abort_mac_scan(pAdapter->pHddCtx,
2338 pScanInfo->sessionId,
2339 eCSR_SCAN_ABORT_DEFAULT);
2340 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002341#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002342 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2343 {
2344 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2345 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2346 {
2347 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2348 actionFrmType);
2349 }
2350 else
2351 {
2352 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2353 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002354 }
2355 }
2356#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002357 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2358 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2359 {
Kumar Anand82c009f2014-05-29 00:29:42 -07002360 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
2361 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002362 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002363 }
2364
Jeff Johnson295189b2012-06-20 16:38:30 -07002365 //Indicate Frame Over Normal Interface
2366 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2367
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002368#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2369 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2370 pbFrames, nFrameLength,
2371 GFP_ATOMIC );
2372#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002373 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2374 pbFrames, nFrameLength,
2375 GFP_ATOMIC );
2376#else
2377 cfg80211_rx_mgmt( pAdapter->dev, freq,
2378 pbFrames, nFrameLength,
2379 GFP_ATOMIC );
2380#endif //LINUX_VERSION_CODE
2381}
2382
2383/*
2384 * ieee80211_add_rx_radiotap_header - add radiotap header
2385 */
2386static int hdd_wlan_add_rx_radiotap_hdr (
2387 struct sk_buff *skb, int rtap_len, int flag )
2388{
2389 u8 rtap_temp[20] = {0};
2390 struct ieee80211_radiotap_header *rthdr;
2391 unsigned char *pos;
2392 u16 rx_flags = 0;
2393
2394 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2395
2396 /* radiotap header, set always present flags */
2397 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2398 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2399 rthdr->it_len = cpu_to_le16(rtap_len);
2400
2401 pos = (unsigned char *) (rthdr + 1);
2402
2403 /* the order of the following fields is important */
2404
2405 /* IEEE80211_RADIOTAP_FLAGS */
2406 *pos = 0;
2407 pos++;
2408
2409 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2410 /* ensure 2 byte alignment for the 2 byte field as required */
2411 if ((pos - (u8 *)rthdr) & 1)
2412 pos++;
2413 put_unaligned_le16(rx_flags, pos);
2414 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302415
Jeff Johnson295189b2012-06-20 16:38:30 -07002416 // actually push the data
2417 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2418
2419 return 0;
2420}
2421
2422static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2423 hdd_cfg80211_state_t* cfgState,
2424 tANI_BOOLEAN actionSendSuccess )
2425{
2426 struct ieee80211_radiotap_header *rthdr;
2427 unsigned char *pos;
2428 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002429#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002430#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2431 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2432#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002433#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002434
2435 /* 2 Byte for TX flags and 1 Byte for Retry count */
2436 u32 rtHdrLen = sizeof(*rthdr) + 3;
2437
2438 u8 *data;
2439
2440 /* We have to return skb with Data starting with MAC header. We have
2441 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2442 * entire skb->len from skb and then we will push cfgState->buf to skb
2443 * */
2444 if( NULL == skb_pull(skb, skb->len) )
2445 {
2446 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2447 kfree_skb(cfgState->skb);
2448 return;
2449 }
2450
2451 data = skb_push( skb, cfgState->len );
2452
2453 if (data == NULL)
2454 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002455 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002456 kfree_skb( cfgState->skb );
2457 return;
2458 }
2459
2460 memcpy( data, cfgState->buf, cfgState->len );
2461
2462 /* send frame to monitor interfaces now */
2463 if( skb_headroom(skb) < rtHdrLen )
2464 {
2465 hddLog( LOGE, FL("No headroom for rtap header"));
2466 kfree_skb(cfgState->skb);
2467 return;
2468 }
2469
2470 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2471
2472 memset( rthdr, 0, rtHdrLen );
2473 rthdr->it_len = cpu_to_le16( rtHdrLen );
2474 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2475 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2476 );
2477
2478 pos = (unsigned char *)( rthdr+1 );
2479
2480 // Fill TX flags
2481 *pos = actionSendSuccess;
2482 pos += 2;
2483
2484 // Fill retry count
2485 *pos = 0;
2486 pos++;
2487
2488 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002489 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002490 skb->pkt_type = PACKET_OTHERHOST;
2491 skb->protocol = htons(ETH_P_802_2);
2492 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002493#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002494#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002495 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002496#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002497#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002498 if (in_interrupt())
2499 netif_rx( skb );
2500 else
2501 netif_rx_ni( skb );
2502
2503 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05302504 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302505 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002506
2507}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302508
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05302509void hdd_p2p_roc_work_queue(struct work_struct *work)
2510{
2511 hdd_adapter_t *pAdapter = container_of(to_delayed_work(work), hdd_adapter_t, roc_work);
2512 hddLog( VOS_TRACE_LEVEL_INFO, FL("%s: "), __func__);
2513 wlan_hdd_p2p_start_remain_on_channel(pAdapter);
2514 return;
2515}
2516