blob: d58699ed433b60de82aea8097a04f3b2633d42d6 [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;
182
183 if( pRemainChanCtx == NULL )
184 {
185 hddLog( LOGW,
186 "%s: No Rem on channel pending for which Rsp is received", __func__);
187 return eHAL_STATUS_SUCCESS;
188 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530189 hddLog( VOS_TRACE_LEVEL_INFO,
190 "Received ROC rsp (request type %d, channel %d, cookie %llu",
191 pRemainChanCtx->rem_on_chan_request,
192 pRemainChanCtx->chan.center_freq,
193 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700194 cfgState->remain_on_chan_ctx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530195 vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
196 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
197 if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
Jeff Johnson295189b2012-06-20 16:38:30 -0700198 {
199 if( cfgState->buf )
200 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530201 hddLog( LOGP,
Jeff Johnson295189b2012-06-20 16:38:30 -0700202 "%s: We need to receive yet an ack from one of tx packet",
203 __func__);
204 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800205 cfg80211_remain_on_channel_expired(
206#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
207 pRemainChanCtx->dev->ieee80211_ptr,
208#else
209 pRemainChanCtx->dev,
210#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700211 pRemainChanCtx->cookie,
212 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700213#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
214 pRemainChanCtx->chan_type,
215#endif
216 GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -0700217 }
218
Jeff Johnson295189b2012-06-20 16:38:30 -0700219
220 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700221 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
222 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700223 )
224 {
225 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800226 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
227 {
228 sme_DeregisterMgmtFrame(
229 hHal, sessionId,
230 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
231 NULL, 0 );
232 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700233 }
234 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
235 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
236 )
237 {
238 WLANSAP_DeRegisterMgmtFrame(
239 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
240 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
241 NULL, 0 );
242 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530243 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
244 && pRemainChanCtx->action_pkt_buff.frame_length != 0)
245 {
246 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
247 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800248 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800249 pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700250 complete(&pAdapter->cancel_rem_on_chan_var);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530251 pAdapter->is_roc_inprogress = FALSE;
252 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700253 return eHAL_STATUS_SUCCESS;
254}
255
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530256VOS_STATUS wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700257{
Jeff Johnson295189b2012-06-20 16:38:30 -0700258 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530259 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700260 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700261
Jeff Johnson32d95a32012-09-10 13:15:23 -0700262 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530264 hddLog(VOS_TRACE_LEVEL_INFO,
265 "Cancel Existing ROC (cookie=%llu)",
266 cfgState->remain_on_chan_ctx->cookie);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700267
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530268 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
269 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE)
270 {
271 hddLog( LOG1,
272 "ROC timer cancellation in progress,"
273 " wait for completion");
274 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
275 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
276 if (0 >= status)
277 {
278 hddLog( LOGE,
279 "%s:wait on cancel_rem_on_chan_var failed %d",
280 __func__, status);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530281 return VOS_STATUS_E_FAILURE;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530282 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530283 return VOS_STATUS_SUCCESS;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530284 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530285
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530286 /* Wait till remain on channel ready indication before issuing cancel
287 * remain on channel request, otherwise if remain on channel not
288 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700289 * will be in unknown state.
290 */
291 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
292 msecs_to_jiffies(WAIT_REM_CHAN_READY));
c_hpothu7f63e882013-10-02 19:13:35 +0530293 if (0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -0700294 {
295 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530296 "%s: timeout waiting for remain on channel ready indication %d",
297 __func__, status);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530298 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
299 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700300 }
301
302 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530303 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530304
Jeff Johnson295189b2012-06-20 16:38:30 -0700305 /* Issue abort remain on chan request to sme.
306 * The remain on channel callback will make sure the remain_on_chan
307 * expired event is sent.
308 */
309 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700310 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
311 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700312 )
313 {
314 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
315 pAdapter->sessionId );
316 }
317 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
318 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
319 )
320 {
321 WLANSAP_CancelRemainOnChannel(
322 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
323 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700324
Jeff Johnson32d95a32012-09-10 13:15:23 -0700325 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700326 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700327
c_hpothu7f63e882013-10-02 19:13:35 +0530328 if (0 >= status)
Jeff Johnson32d95a32012-09-10 13:15:23 -0700329 {
330 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530331 "%s: timeout waiting for cancel remain on channel ready indication %d",
332 __func__, status);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700333 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530334 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700335 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530336 return VOS_STATUS_SUCCESS;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700337}
338
339int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
340{
341 int status = 0;
342 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
343
344 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
345 {
346 //Cancel Existing Remain On Channel
347 //If no action frame is pending
348 if( cfgState->remain_on_chan_ctx != NULL)
349 {
350 //Check whether Action Frame is pending or not
351 if( cfgState->buf == NULL)
352 {
353 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
354 }
355 else
356 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530357 hddLog(VOS_TRACE_LEVEL_DEBUG,
358 "Cannot Cancel Existing Remain on Channel");
Jeff Johnson32d95a32012-09-10 13:15:23 -0700359 status = -EBUSY;
360 }
361 }
362 }
363 return status;
364}
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530365void wlan_hdd_remain_on_chan_timeout(void *data)
366{
367 hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
368 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
369 hdd_cfg80211_state_t *cfgState;
370 if ( NULL == pAdapter )
371 {
372 hddLog( LOGE, FL("pAdapter is NULL !!!"));
373 return;
374 }
375 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
376 pRemainChanCtx = cfgState->remain_on_chan_ctx;
377 if (NULL == pRemainChanCtx)
378 {
379 hddLog( LOGE, FL("No Remain on channel is pending"));
380 return;
381 }
382 if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
383 {
384 hddLog( LOGE, FL("Cancellation already in progress"));
385 return;
386 }
387
388 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
389 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
390 hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
391 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
392 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
393 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
394 )
395 {
396 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
397 pAdapter->sessionId );
398 }
399 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
400 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
401 )
402 {
403 WLANSAP_CancelRemainOnChannel(
404 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
405 }
406 hdd_allow_suspend();
407}
Jeff Johnson32d95a32012-09-10 13:15:23 -0700408
409static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
410 struct net_device *dev,
411 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700412#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700413 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700414#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700415 unsigned int duration, u64 *cookie,
416 rem_on_channel_request_type_t request_type )
417{
418 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
419 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
420 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530421 VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
422 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
423 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
424 hdd_adapter_t *pAdapter_temp;
425 VOS_STATUS status;
426 v_BOOL_t isGoPresent = VOS_FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530427 VOS_STATUS checkReadyInd;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700428 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
429 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700430#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530431 hddLog(VOS_TRACE_LEVEL_INFO,
432 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
433 " request type %d, cookie %llu",
434 chan->hw_value, chan->center_freq, channel_type, duration,
435 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700436#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530437 hddLog(VOS_TRACE_LEVEL_INFO,
438 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
439 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
440 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700441#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700442 //Cancel existing remain On Channel if any
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530443 checkReadyInd = wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
444 if (VOS_STATUS_SUCCESS != checkReadyInd)
445 {
446 hddLog( LOGE, FL("Cancel Roc in progress"));
447 return -EBUSY;
448 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700449
Jeff Johnsone7245742012-09-05 17:12:55 -0700450 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700451 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700452 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700453 * channel requets when Load/Unload is in progress*/
Rashmi Ramannab1429032014-04-26 14:59:09 +0530454 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(((hdd_context_t *)pAdapter->pHddCtx))
Ganesh Kondabattiniaeb7b772014-08-11 20:00:36 +0530455 || hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx, VOS_TRUE))
Jeff Johnson295189b2012-06-20 16:38:30 -0700456 {
457 hddLog( LOGE,
Rashmi Ramannab1429032014-04-26 14:59:09 +0530458 "%s: Wlan Load/Unload or Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700459 return -EBUSY;
460 }
461
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700462 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
463 {
464 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
465 "%s:LOGP in Progress. Ignore!!!", __func__);
466 return -EAGAIN;
467 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700468 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
469 if( NULL == pRemainChanCtx )
470 {
471 hddLog(VOS_TRACE_LEVEL_FATAL,
472 "%s: Not able to allocate memory for Channel context",
473 __func__);
474 return -ENOMEM;
475 }
476
477 vos_mem_copy( &pRemainChanCtx->chan, chan,
478 sizeof(struct ieee80211_channel) );
479
Yue Maf49ba872013-08-19 12:04:25 -0700480#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700481 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700482#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700483 pRemainChanCtx->duration = duration;
484 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800485 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700486 pRemainChanCtx->cookie = *cookie;
487 pRemainChanCtx->rem_on_chan_request = request_type;
488 cfgState->remain_on_chan_ctx = pRemainChanCtx;
489 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530490 pRemainChanCtx->action_pkt_buff.freq = 0;
491 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
492 pRemainChanCtx->action_pkt_buff.frame_length = 0;
493 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530494 pRemainChanCtx->is_pending_roc_cancelled = FALSE;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530495 /* Initialize Remain on chan timer */
496 vos_status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
497 VOS_TIMER_TYPE_SW,
498 wlan_hdd_remain_on_chan_timeout,
499 pAdapter);
500 if (vos_status != VOS_STATUS_SUCCESS)
501 {
502 hddLog(VOS_TRACE_LEVEL_ERROR,
503 "%s: Not able to initalize remain_on_chan timer", __func__);
504 }
505 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
506 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
507 {
508 pAdapter_temp = pAdapterNode->pAdapter;
509 if (WLAN_HDD_P2P_GO == pAdapter_temp->device_mode)
510 {
511 isGoPresent = VOS_TRUE;
512 }
513 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
514 pAdapterNode = pNext;
515 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530516 hdd_prevent_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700517 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
518
519 //call sme API to start remain on channel.
520 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700521 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
522 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700523 )
524 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700525 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700526 //call sme API to start remain on channel.
527 sme_RemainOnChannel(
Rashmi Ramannac7744532013-10-06 16:49:08 +0530528 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
529 chan->hw_value, duration,
530 wlan_hdd_remain_on_channel_callback, pAdapter,
531 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700532
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800533 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
534 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530535 if( eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame(
536 WLAN_HDD_GET_HAL_CTX(pAdapter),
537 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
538 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ))
539 {
540 hddLog(VOS_TRACE_LEVEL_ERROR,
541 "sme_RegisterMgmtFrame returned fail");
542 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800543 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700544
545 }
546 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
547 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
548 )
549 {
550 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700551 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700552 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
553 chan->hw_value, duration,
554 wlan_hdd_remain_on_channel_callback, pAdapter ))
555
556 {
557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
558 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
559 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700560 vos_mem_free (pRemainChanCtx);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530561 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700562 return -EINVAL;
563 }
564
565
Jeff Johnson43971f52012-07-17 12:26:56 -0700566 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700567 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
568 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
569 NULL, 0 ))
570 {
571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
572 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
573 WLANSAP_CancelRemainOnChannel(
574 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530575 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700576 return -EINVAL;
577 }
578
579 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530580
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530581 pAdapter->is_roc_inprogress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700582 return 0;
583
584}
585
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530586int __wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800587#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
588 struct wireless_dev *wdev,
589#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700590 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800591#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700592 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700593#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700594 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700595#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700596 unsigned int duration, u64 *cookie )
597{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800598#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
599 struct net_device *dev = wdev->netdev;
600#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530601 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
602
603 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
604 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
605 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Jeff Johnson295189b2012-06-20 16:38:30 -0700606 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700607 chan,
608#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
609 channel_type,
610#endif
611 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700612 REMAIN_ON_CHANNEL_REQUEST);
613}
614
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530615int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
616#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
617 struct wireless_dev *wdev,
618#else
619 struct net_device *dev,
620#endif
621 struct ieee80211_channel *chan,
622#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
623 enum nl80211_channel_type channel_type,
624#endif
625 unsigned int duration, u64 *cookie )
626{
627 int ret;
628
629 vos_ssr_protect(__func__);
630 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
631#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
632 wdev,
633#else
634 dev,
635#endif
636 chan,
637#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
638 channel_type,
639#endif
640 duration, cookie);
641 vos_ssr_unprotect(__func__);
642
643 return ret;
644}
645
646
Jeff Johnson295189b2012-06-20 16:38:30 -0700647void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
648{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530649 hdd_cfg80211_state_t *cfgState = NULL;
650 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530651 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530652 if (NULL == pAdapter)
653 {
654 hddLog(LOGE, FL("pAdapter is NULL"));
655 return;
656 }
657 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
658 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530659 hddLog( LOG1, "Ready on chan ind");
Jeff Johnson295189b2012-06-20 16:38:30 -0700660 if( pRemainChanCtx != NULL )
661 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530662 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
663 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
664 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530665 //start timer for actual duration
666 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
667 (pRemainChanCtx->duration));
668 if (VOS_STATUS_SUCCESS!=status)
669 {
670 hddLog( LOGE, FL("Remain on Channel timer start failed"));
671 }
672 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700673 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800674 cfg80211_ready_on_channel(
675#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
676 pAdapter->dev->ieee80211_ptr,
677#else
678 pAdapter->dev,
679#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800680 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700681 &pRemainChanCtx->chan,
682#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
683 pRemainChanCtx->chan_type,
684#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700685 pRemainChanCtx->duration, GFP_KERNEL );
686 }
687#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530688 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700689 {
690 complete(&pAdapter->offchannel_tx_event);
691 }
692#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530693 // Check for cached action frame
694 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
695 {
696#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
697 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
698 pRemainChanCtx->action_pkt_buff.freq, 0,
699 pRemainChanCtx->action_pkt_buff.frame_ptr,
700 pRemainChanCtx->action_pkt_buff.frame_length,
701 GFP_ATOMIC );
702#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
703 cfg80211_rx_mgmt( pAdapter->dev,
704 pRemainChanCtx->action_pkt_buff.freq, 0,
705 pRemainChanCtx->action_pkt_buff.frame_ptr,
706 pRemainChanCtx->action_pkt_buff.frame_length,
707 GFP_ATOMIC );
708#else
709 cfg80211_rx_mgmt( pAdapter->dev,
710 pRemainChanCtx->action_pkt_buff.freq,
711 pRemainChanCtx->action_pkt_buff.frame_ptr,
712 pRemainChanCtx->action_pkt_buff.frame_length,
713 GFP_ATOMIC );
714#endif //LINUX_VERSION_CODE
715 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
716 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
717 pRemainChanCtx->action_pkt_buff.frame_length = 0;
718 pRemainChanCtx->action_pkt_buff.freq = 0;
719 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
720 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530721 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
722 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700723 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530724 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
725 {
726 /* since pRemainChanCtx->is_pending_roc_cancelled is
727 * set, it means Cancel Reamain on channel command is
728 * pending because remain on channel event was not
729 * ready when cancel ROC was issued.So issue
730 * cancel ROC now.
731 */
732 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
733 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700734 }
735 else
736 {
737 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
738 }
739 return;
740}
741
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530742int __wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800743#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
744 struct wireless_dev *wdev,
745#else
746 struct net_device *dev,
747#endif
748 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700749{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800750#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
751 struct net_device *dev = wdev->netdev;
752#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700753 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700754 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530755 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530756 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
757 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530758 u64 cookie_dummy;
759 cookie_dummy = cookie << 32;
760 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
761 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
762 pAdapter->sessionId, cookie_dummy));
763 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -0700764
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530765 status = wlan_hdd_validate_context(pHddCtx);
766
767 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700768 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
770 "%s: HDD context is not valid", __func__);
771 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700772 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530773 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
774
Jeff Johnson295189b2012-06-20 16:38:30 -0700775 /* FIXME cancel currently running remain on chan.
776 * Need to check cookie and cancel accordingly
777 */
778 if( (cfgState->remain_on_chan_ctx == NULL) ||
779 (cfgState->remain_on_chan_ctx->cookie != cookie) )
780 {
781 hddLog( LOGE,
782 "%s: No Remain on channel pending with specified cookie value",
783 __func__);
784 return -EINVAL;
785 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530786 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
787 {
788 /* wait until remain on channel ready event received
789 * for already issued remain on channel request */
790 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
791 msecs_to_jiffies(WAIT_REM_CHAN_READY));
792 if (0 >= status)
793 {
794 hddLog( LOGE,
795 "%s: timeout waiting for remain on channel ready indication %d",
796 __func__, status);
797 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
798 return 0;
799
800 }
801 }
802 else
803 {
804 hddLog( LOG1, FL("Cancel ROC event is already pending, "
805 "waiting for ready on channel indication.") );
806 return 0;
807 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530808 if (NULL != cfgState->remain_on_chan_ctx)
809 {
810 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
811 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
812 {
813 hddLog( LOG1,
814 FL("ROC timer cancellation in progress,"
815 " wait for completion"));
816 status = wait_for_completion_interruptible_timeout(
817 &pAdapter->cancel_rem_on_chan_var,
818 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
819 if (0 >= status)
820 {
821 hddLog( LOGE,
822 "%s:wait on cancel_rem_on_chan_var failed %d",
823 __func__, status);
824 }
825 return 0;
826 }
827 else
828 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
829 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700830 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
831 /* Issue abort remain on chan request to sme.
832 * The remain on channel callback will make sure the remain_on_chan
833 * expired event is sent.
834 */
835 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700836 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
837 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700838 )
839 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530840 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700841 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
842 sessionId );
843 }
844 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
845 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
846 )
847 {
848 WLANSAP_CancelRemainOnChannel(
849 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
850 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530851 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700852 {
853 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
854 __func__, pAdapter->device_mode);
855 return -EIO;
856 }
c_hpothu7f63e882013-10-02 19:13:35 +0530857 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700858 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +0530859 if (0 >= status)
860 {
861 hddLog( LOGE,
862 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
863 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530864 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700865 return 0;
866}
867
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530868int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800869#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530870 struct wireless_dev *wdev,
871#else
872 struct net_device *dev,
873#endif
874 u64 cookie )
875{
876 int ret;
877
878 vos_ssr_protect(__func__);
879 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
880#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
881 wdev,
882#else
883 dev,
884#endif
885 cookie);
886 vos_ssr_unprotect(__func__);
887
888 return ret;
889}
890
891
892#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
893int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800894 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700895#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800896 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700897 bool channel_type_valid,
898#endif
899 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800900 const u8 *buf, size_t len, bool no_cck,
901 bool dont_wait_for_ack, u64 *cookie )
902#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530903int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700904 struct ieee80211_channel *chan, bool offchan,
905 enum nl80211_channel_type channel_type,
906 bool channel_type_valid, unsigned int wait,
907 const u8 *buf, size_t len, bool no_cck,
908 bool dont_wait_for_ack, u64 *cookie )
909#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530910int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700911 struct ieee80211_channel *chan, bool offchan,
912 enum nl80211_channel_type channel_type,
913 bool channel_type_valid, unsigned int wait,
914 const u8 *buf, size_t len, u64 *cookie )
915#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530916int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700917 struct ieee80211_channel *chan,
918 enum nl80211_channel_type channel_type,
919 bool channel_type_valid,
920 const u8 *buf, size_t len, u64 *cookie )
921#endif //LINUX_VERSION_CODE
922{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800923#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
924 struct net_device *dev = wdev->netdev;
925#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700926 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +0530927 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
928 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
929 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700930 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
931 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
Mukul Sharma1e5d0b72014-07-01 19:22:21 +0530932 tActionFrmType actionFrmType = WLAN_HDD_ACTION_FRM_TYPE_MAX;
Jeff Johnsone7245742012-09-05 17:12:55 -0700933 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530934 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -0700935
Jeff Johnson295189b2012-06-20 16:38:30 -0700936#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
937 hdd_adapter_t *goAdapter;
938#endif
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +0530939
940 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530941 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
942 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530943 status = wlan_hdd_validate_context(pHddCtx);
944
945 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800946 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
948 "%s: HDD context is not valid", __func__);
949 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800950 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530951
c_hpothu7f63e882013-10-02 19:13:35 +0530952 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
953 __func__, pAdapter->device_mode, type);
954
955
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700956 if ((type == SIR_MAC_MGMT_FRAME) &&
957 (subType == SIR_MAC_MGMT_ACTION) &&
958 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
959 {
960 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Kaushik, Sushant731e8942014-09-08 11:59:19 +0530961#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800962 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700963 {
964 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
965 actionFrmType);
966 }
967 else
968 {
969 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
970 p2p_action_frame_type[actionFrmType]);
971 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
972 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
973 {
974 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
975 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800976 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700977 }
978 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
979 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
980 {
981 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
982 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
983 " completed state");
984 }
985 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700986#endif
Kaushik, Sushant731e8942014-09-08 11:59:19 +0530987 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700988
Jeff Johnsone7245742012-09-05 17:12:55 -0700989#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
990 noack = dont_wait_for_ack;
991#endif
992
993 //If the wait is coming as 0 with off channel set
994 //then set the wait to 200 ms
995 if (offchan && !wait)
996 wait = ACTION_FRAME_DEFAULT_WAIT;
997
Jeff Johnson295189b2012-06-20 16:38:30 -0700998 //Call sme API to send out a action frame.
999 // OR can we send it directly through data path??
1000 // After tx completion send tx status back.
1001 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1002 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1003 )
1004 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001005 if (type == SIR_MAC_MGMT_FRAME)
1006 {
1007 if (subType == SIR_MAC_MGMT_PROBE_RSP)
1008 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301009 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -07001010 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301011 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001012 goto err_rem_channel;
1013 }
1014 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
1015 (subType == SIR_MAC_MGMT_DEAUTH))
1016 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001017 /* During EAP failure or P2P Group Remove supplicant
1018 * is sending del_station command to driver. From
1019 * del_station function, Driver will send deauth frame to
1020 * p2p client. No need to send disassoc frame from here.
1021 * so Drop the frame here and send tx indication back to
1022 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -07001023 */
1024 tANI_U8 dstMac[ETH_ALEN] = {0};
1025 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07001026 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001027 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -08001028 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001029 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08001030 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001031 goto err_rem_channel;
1032 }
1033 }
1034 }
1035
1036 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001037 {
1038 if ( !noack )
1039 {
1040 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1041 __func__);
1042 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1043 }
1044 else
1045 {
1046 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1047 __func__);
1048 return -EBUSY;
1049 }
1050 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001051
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301052 if( subType == SIR_MAC_MGMT_ACTION)
1053 {
1054 hddLog( LOG1, "Action frame tx request : %s",
1055 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1056 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001057
1058#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1059 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1060
1061 //If GO adapter exists and operating on same frequency
1062 //then we will not request remain on channel
1063 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1064 == goAdapter->sessionCtx.ap.operatingChannel ) )
1065 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301066 /* if GO exist and is not off channel
1067 * wait time should be zero.
1068 */
1069 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001070 goto send_frame;
1071 }
1072#endif
1073
1074#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1075 if( offchan && wait)
1076 {
1077 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301078 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001079 // In case of P2P Client mode if we are already
1080 // on the same channel then send the frame directly
1081
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301082 if( (cfgState->remain_on_chan_ctx != NULL) &&
1083 (cfgState->current_freq == chan->center_freq)
1084 )
1085 {
1086 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1087 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301088 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301089 /* Some times FW is taking almost 500 msec for
1090 * full 15 retries, which leads to ROC expiration
1091 * by the time peer gets response from other peer.
1092 * Therefore as part of temporary fix , in host
1093 * ROC time is extended. For frames where we are
1094 * expecting response from peer , its extended by
1095 * 500 msec to make ROC wait time as 1 sec and
1096 * in other cases its extended by 300 msec to make
1097 * total ROC wait as 500 msec.
1098 * TODO: FW needs to fix as why 15 retry is taking
1099 * such long time.
1100 */
1101 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1102 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1103 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1104 wait = wait + ACTION_FRAME_RSP_WAIT;
1105 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1106 actionFrmType == WLAN_HDD_INVITATION_RESP )
1107 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301108 vos_timer_stop(
1109 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1110 status = vos_timer_start(
1111 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1112 wait);
1113 if ( status != VOS_STATUS_SUCCESS )
vamsida0e5ab2013-12-26 14:33:27 +05301114 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301115 hddLog( LOGE, "Remain on Channel timer start failed");
1116 }
1117
1118 hddLog(VOS_TRACE_LEVEL_INFO,
1119 "action frame: extending the wait time %u",
1120 wait);
1121 goto send_frame;
1122 }
1123 else
1124 {
1125 if ( TRUE ==
1126 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1127 {
1128 hddLog(VOS_TRACE_LEVEL_INFO,
1129 "action frame tx: waiting for completion of ROC ");
1130
1131 status = wait_for_completion_interruptible_timeout(
1132 &pAdapter->cancel_rem_on_chan_var,
1133 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1134 if (0 >= status)
1135 {
1136 hddLog( LOGE,
1137 "%s:wait on cancel_rem_on_chan_var failed %d",
1138 __func__, status);
1139 }
vamsida0e5ab2013-12-26 14:33:27 +05301140 }
1141 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301142 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301143 hddLog(VOS_TRACE_LEVEL_INFO,
1144 "action frame: Request ROC for wait time %u", wait);
1145
Jeff Johnson295189b2012-06-20 16:38:30 -07001146 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001147 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001148 chan,
1149#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1150 channel_type,
1151#endif
1152 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301153 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001154
1155 if(0 != status)
1156 {
1157 if( (-EBUSY == status) &&
1158 (cfgState->current_freq == chan->center_freq) )
1159 {
1160 goto send_frame;
1161 }
1162 goto err_rem_channel;
1163 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001164 /* Wait for driver to be ready on the requested channel */
1165 status = wait_for_completion_interruptible_timeout(
1166 &pAdapter->offchannel_tx_event,
1167 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301168 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001169 {
c_hpothu7f63e882013-10-02 19:13:35 +05301170 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001171 goto err_rem_channel;
1172 }
1173 }
1174 else if ( offchan )
1175 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001176 /* Check before sending action frame
1177 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001178 if(NULL == cfgState->remain_on_chan_ctx)
1179 {
1180 goto err_rem_channel;
1181 }
1182 }
1183 send_frame:
1184#endif
1185
Jeff Johnsone7245742012-09-05 17:12:55 -07001186 if(!noack)
1187 {
1188 cfgState->buf = vos_mem_malloc( len ); //buf;
1189 if( cfgState->buf == NULL )
1190 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001191
Jeff Johnsone7245742012-09-05 17:12:55 -07001192 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001193
Jeff Johnsone7245742012-09-05 17:12:55 -07001194 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001195
1196#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001197 if( cfgState->remain_on_chan_ctx )
1198 {
1199 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1200 *cookie = cfgState->action_cookie;
1201 }
1202 else
1203 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001204#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001205 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001206 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001207#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001208 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001209#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301210 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001211
1212 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001213 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1214 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001215 )
1216 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001217 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001218
Jeff Johnsone7245742012-09-05 17:12:55 -07001219 if ((type == SIR_MAC_MGMT_FRAME) &&
1220 (subType == SIR_MAC_MGMT_ACTION) &&
1221 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001222 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001223 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301224 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001225 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001226 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001227 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301228 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001229 }
1230 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1231 {
1232 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301233 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001234 }
1235 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301236
Jeff Johnson295189b2012-06-20 16:38:30 -07001237 if (eHAL_STATUS_SUCCESS !=
1238 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301239 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001240 {
1241 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1242 "%s: sme_sendAction returned fail", __func__);
1243 goto err;
1244 }
1245 }
1246 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1247 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1248 )
1249 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001250 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001251 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001252 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001253 {
1254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1255 "%s: WLANSAP_SendAction returned fail", __func__);
1256 goto err;
1257 }
1258 }
1259
1260 return 0;
1261err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001262 if(!noack)
1263 {
1264 hdd_sendActionCnf( pAdapter, FALSE );
1265 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001266 return 0;
1267err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001268 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001269 cfg80211_mgmt_tx_status(
1270#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1271 pAdapter->dev->ieee80211_ptr,
1272#else
1273 pAdapter->dev,
1274#endif
1275 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 return 0;
1277}
1278
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301279#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1280int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
1281 struct ieee80211_channel *chan, bool offchan,
1282#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1283 enum nl80211_channel_type channel_type,
1284 bool channel_type_valid,
1285#endif
1286 unsigned int wait,
1287 const u8 *buf, size_t len, bool no_cck,
1288 bool dont_wait_for_ack, u64 *cookie )
1289#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1290int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1291 struct ieee80211_channel *chan, bool offchan,
1292 enum nl80211_channel_type channel_type,
1293 bool channel_type_valid, unsigned int wait,
1294 const u8 *buf, size_t len, bool no_cck,
1295 bool dont_wait_for_ack, u64 *cookie )
1296#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1297int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1298 struct ieee80211_channel *chan, bool offchan,
1299 enum nl80211_channel_type channel_type,
1300 bool channel_type_valid, unsigned int wait,
1301 const u8 *buf, size_t len, u64 *cookie )
1302#else
1303int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1304 struct ieee80211_channel *chan,
1305 enum nl80211_channel_type channel_type,
1306 bool channel_type_valid,
1307 const u8 *buf, size_t len, u64 *cookie )
1308#endif //LINUX_VERSION_CODE
1309{
1310 int ret;
1311
1312 vos_ssr_protect(__func__);
1313#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1314 ret = __wlan_hdd_mgmt_tx(wiphy, wdev,
1315 chan, offchan,
1316#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1317 channel_type,
1318 channel_type_valid,
1319#endif
1320 wait,
1321 buf, len, no_cck,
1322 dont_wait_for_ack, cookie);
1323#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1324 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1325 channel_type, channel_type_valid, wait,
1326 buf, len, no_cck,
1327 dont_wait_for_ack, cookie);
1328#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1329 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1330 channel_type, channel_type_valid, wait,
1331 buf, len, cookie);
1332#else
1333 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, channel_type,
1334 channel_type_valid, buf, len, cookie);
1335#endif //LINUX_VERSION_CODE
1336 vos_ssr_unprotect(__func__);
1337
1338 return ret;
1339}
1340
Jeff Johnson295189b2012-06-20 16:38:30 -07001341#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001342#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301343int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001344 struct wireless_dev *wdev,
1345 u64 cookie)
1346{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301347 u64 cookie_dummy;
1348 cookie_dummy = cookie << 32;
1349 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1350 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001351 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1352}
1353#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301354int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001355 struct net_device *dev,
1356 u64 cookie)
1357{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301358 u64 cookie_dummy;
1359 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1360 cookie_dummy = cookie << 32;
1361 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1362 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1363 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001364 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1365}
1366#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001367#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001368
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301369#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1370#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1371int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1372 struct wireless_dev *wdev,
1373 u64 cookie)
1374{
1375 int ret;
1376
1377 vos_ssr_protect(__func__);
1378 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1379 vos_ssr_unprotect(__func__);
1380
1381 return ret;
1382}
1383#else
1384int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1385 struct net_device *dev,
1386 u64 cookie)
1387{
1388 int ret;
1389
1390 vos_ssr_protect(__func__);
1391 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie);
1392 vos_ssr_unprotect(__func__);
1393
1394 return ret;
1395}
1396#endif
1397#endif
1398
Jeff Johnson295189b2012-06-20 16:38:30 -07001399void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1400{
1401 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1402
Jeff Johnsone7245742012-09-05 17:12:55 -07001403 cfgState->actionFrmState = HDD_IDLE;
1404
Jeff Johnson295189b2012-06-20 16:38:30 -07001405 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1406 if( NULL == cfgState->buf )
1407 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001408 return;
1409 }
1410
1411 /* If skb is NULL it means this packet was received on CFG80211 interface
1412 * else it was received on Monitor interface */
1413 if( cfgState->skb == NULL )
1414 {
1415 /*
1416 * buf is the same pointer it passed us to send. Since we are sending
1417 * it through control path, we use different buffers.
1418 * In case of mac80211, they just push it to the skb and pass the same
1419 * data while sending tx ack status.
1420 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001421 cfg80211_mgmt_tx_status(
1422#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1423 pAdapter->dev->ieee80211_ptr,
1424#else
1425 pAdapter->dev,
1426#endif
1427 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001428 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1429 vos_mem_free( cfgState->buf );
1430 cfgState->buf = NULL;
1431 }
1432 else
1433 {
1434 hdd_adapter_t* pMonAdapter =
1435 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1436 if( pMonAdapter == NULL )
1437 {
1438 hddLog( LOGE, "Not able to get Monitor Adapter");
1439 cfgState->skb = NULL;
1440 vos_mem_free( cfgState->buf );
1441 cfgState->buf = NULL;
1442 complete(&pAdapter->tx_action_cnf_event);
1443 return;
1444 }
1445 /* Send TX completion feedback over monitor interface. */
1446 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1447 cfgState->skb = NULL;
1448 vos_mem_free( cfgState->buf );
1449 cfgState->buf = NULL;
1450 /* Look for the next Mgmt packet to TX */
1451 hdd_mon_tx_mgmt_pkt(pAdapter);
1452 }
1453 complete(&pAdapter->tx_action_cnf_event);
1454}
1455
1456/**
1457 * hdd_setP2pNoa
1458 *
1459 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301460 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001461 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1462 *
1463 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301464 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001465 *
1466 *ASSUMPTIONS:
1467 *
1468 *
1469 *NOTE:
1470 *
1471 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301472 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001473 *
1474 * @return Status
1475 */
1476
1477int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1478{
1479 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1480 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1481 VOS_STATUS status = VOS_STATUS_SUCCESS;
1482 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001483 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001484 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001485 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001486
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001487 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001488 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301489 {
1490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1491 "%s: strnchr failed to find delimeter",__func__);
1492 return -EINVAL;
1493 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001494 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001495 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1496 if (ret < 3)
1497 {
1498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1499 "%s: P2P_SET GO NoA: fail to read param "
1500 "count=%d duration=%d interval=%d \n",
1501 __func__, count, start_time, duration);
1502 return -EINVAL;
1503 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001505 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001506 __func__, count, start_time, duration);
1507 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001508 /* PS Selection
1509 * Periodic NoA (2)
1510 * Single NOA (4)
1511 */
1512 NoA.opp_ps = 0;
1513 NoA.ctWindow = 0;
1514 if (count == 1)
1515 {
1516 NoA.duration = 0;
1517 NoA.single_noa_duration = duration;
1518 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1519 }
1520 else
1521 {
1522 NoA.duration = duration;
1523 NoA.single_noa_duration = 0;
1524 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1525 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001526 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001527 NoA.count = count;
1528 NoA.sessionid = pAdapter->sessionId;
1529
1530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1531 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1532 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001533 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001534 NoA.ctWindow, NoA.duration, NoA.interval,
1535 NoA.count, NoA.single_noa_duration,
1536 NoA.psSelection);
1537
1538 sme_p2pSetPs(hHal, &NoA);
1539 return status;
1540}
1541
1542/**
1543 * hdd_setP2pOpps
1544 *
1545 *FUNCTION:
1546 * This function is called from hdd_hostapd_ioctl function when Driver
1547 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1548 *
1549 *LOGIC:
1550 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1551 *
1552 *ASSUMPTIONS:
1553 *
1554 *
1555 *NOTE:
1556 *
1557 * @param dev Pointer to net device structure
1558 * @param command Pointer to command
1559 *
1560 * @return Status
1561 */
1562
1563int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1564{
1565 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1566 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1567 VOS_STATUS status = VOS_STATUS_SUCCESS;
1568 tP2pPsConfig NoA;
1569 char *param;
1570 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001571 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001572
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001573 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001574 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301575 {
1576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1577 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001578 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301579 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001580 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001581 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1582 if (ret < 3)
1583 {
1584 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1585 "%s: P2P_SET GO PS: fail to read param "
1586 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1587 __func__, legacy_ps, opp_ps, ctwindow);
1588 return -EINVAL;
1589 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001590 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001591 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 __func__, legacy_ps, opp_ps, ctwindow);
1593
1594 /* PS Selection
1595 * Opportunistic Power Save (1)
1596 */
1597
1598 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1599 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301600 * values are coming from wpa_supplicant as -1.
1601 * Example : User want to set ctWindow with 30 then wpa_cli command :
1602 * P2P_SET ctwindow 30
1603 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001604 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301605 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001606 if (ctwindow != -1)
1607 {
1608
1609 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001610 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001611 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1612
1613 if (ctwindow != pAdapter->ctw)
1614 {
1615 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301616
Jeff Johnson295189b2012-06-20 16:38:30 -07001617 if(pAdapter->ops)
1618 {
1619 NoA.opp_ps = pAdapter->ops;
1620 NoA.ctWindow = pAdapter->ctw;
1621 NoA.duration = 0;
1622 NoA.single_noa_duration = 0;
1623 NoA.interval = 0;
1624 NoA.count = 0;
1625 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1626 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301627
Jeff Johnson295189b2012-06-20 16:38:30 -07001628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1629 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1630 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001631 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001632 NoA.ctWindow, NoA.duration, NoA.interval,
1633 NoA.count, NoA.single_noa_duration,
1634 NoA.psSelection);
1635
1636 sme_p2pSetPs(hHal, &NoA);
1637 }
1638 return 0;
1639 }
1640 }
1641
1642 if (opp_ps != -1)
1643 {
1644 pAdapter->ops = opp_ps;
1645
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301646 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001647 {
1648 NoA.opp_ps = opp_ps;
1649 NoA.ctWindow = pAdapter->ctw;
1650 NoA.duration = 0;
1651 NoA.single_noa_duration = 0;
1652 NoA.interval = 0;
1653 NoA.count = 0;
1654 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1655 NoA.sessionid = pAdapter->sessionId;
1656
1657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1658 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1659 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001660 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 NoA.ctWindow, NoA.duration, NoA.interval,
1662 NoA.count, NoA.single_noa_duration,
1663 NoA.psSelection);
1664
1665 sme_p2pSetPs(hHal, &NoA);
1666 }
1667 }
1668 return status;
1669}
1670
1671int hdd_setP2pPs( struct net_device *dev, void *msgData )
1672{
1673 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1674 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1675 VOS_STATUS status = VOS_STATUS_SUCCESS;
1676 tP2pPsConfig NoA;
1677 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1678
1679 NoA.opp_ps = pappNoA->opp_ps;
1680 NoA.ctWindow = pappNoA->ctWindow;
1681 NoA.duration = pappNoA->duration;
1682 NoA.interval = pappNoA->interval;
1683 NoA.count = pappNoA->count;
1684 NoA.single_noa_duration = pappNoA->single_noa_duration;
1685 NoA.psSelection = pappNoA->psSelection;
1686 NoA.sessionid = pAdapter->sessionId;
1687
1688 sme_p2pSetPs(hHal, &NoA);
1689 return status;
1690}
Jeff Johnson295189b2012-06-20 16:38:30 -07001691
1692static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1693{
1694 tANI_U8 sessionType;
1695
1696 switch( type )
1697 {
1698 case NL80211_IFTYPE_AP:
1699 sessionType = WLAN_HDD_SOFTAP;
1700 break;
1701 case NL80211_IFTYPE_P2P_GO:
1702 sessionType = WLAN_HDD_P2P_GO;
1703 break;
1704 case NL80211_IFTYPE_P2P_CLIENT:
1705 sessionType = WLAN_HDD_P2P_CLIENT;
1706 break;
1707 case NL80211_IFTYPE_STATION:
1708 sessionType = WLAN_HDD_INFRA_STATION;
1709 break;
1710 case NL80211_IFTYPE_MONITOR:
1711 sessionType = WLAN_HDD_MONITOR;
1712 break;
1713 default:
1714 sessionType = WLAN_HDD_INFRA_STATION;
1715 break;
1716 }
1717
1718 return sessionType;
1719}
1720
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001721#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301722struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001723 struct wiphy *wiphy, const char *name,
1724 enum nl80211_iftype type,
1725 u32 *flags, struct vif_params *params )
1726#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301727struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001728 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1729 u32 *flags, struct vif_params *params )
1730#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301731struct net_device* __wlan_hdd_add_virtual_intf(
Jeff Johnson295189b2012-06-20 16:38:30 -07001732 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1733 u32 *flags, struct vif_params *params )
1734#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301735int __wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
Jeff Johnson295189b2012-06-20 16:38:30 -07001736 enum nl80211_iftype type,
1737 u32 *flags, struct vif_params *params )
1738#endif
1739{
1740 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301741 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301742 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001743 ENTER();
1744
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301745 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1746 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301747 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1748 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1749 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001750 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001751 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001752 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05301753#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1754 return ERR_PTR(-EINVAL);
1755#else
1756 return -EAGAIN;
1757#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001758 }
1759
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001760 if (pHddCtx->isLogpInProgress)
1761 {
1762 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1763 "%s:LOGP in Progress. Ignore!!!", __func__);
1764#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301765 return ERR_PTR(-EINVAL);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001766#else
1767 return -EAGAIN;
1768#endif
1769 }
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301770
1771 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1772 pScanInfo = &pHddCtx->scan_info;
1773 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1774 (pHddCtx->scan_info.mScanPending))
1775 {
1776 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1777 eCSR_SCAN_ABORT_DEFAULT);
1778 hddLog(VOS_TRACE_LEVEL_INFO,
1779 "%s: Abort Scan while adding virtual interface",__func__);
1780 }
1781
1782 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05301783 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1784 ((NL80211_IFTYPE_P2P_GO == type) ||
1785 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001786 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001787 /* Generate the P2P Interface Address. this address must be
1788 * different from the P2P Device Address.
1789 */
1790 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1791 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301792 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001793 wlan_hdd_get_session_type(type),
1794 name, p2pDeviceAddress.bytes,
1795 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001796 }
1797 else
1798 {
1799 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1800 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1801 }
1802
1803 if( NULL == pAdapter)
1804 {
1805 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1806#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301807 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001808#else
1809 return -EINVAL;
1810#endif
1811 }
1812 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001813#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1814 return pAdapter->dev->ieee80211_ptr;
1815#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001816 return pAdapter->dev;
1817#else
1818 return 0;
1819#endif
1820}
1821
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301822#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1823struct wireless_dev* wlan_hdd_add_virtual_intf(
1824 struct wiphy *wiphy, const char *name,
1825 enum nl80211_iftype type,
1826 u32 *flags, struct vif_params *params )
1827#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1828struct wireless_dev* wlan_hdd_add_virtual_intf(
1829 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1830 u32 *flags, struct vif_params *params )
1831#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1832struct net_device* wlan_hdd_add_virtual_intf(
1833 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1834 u32 *flags, struct vif_params *params )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001835#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301836int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1837 enum nl80211_iftype type,
1838 u32 *flags, struct vif_params *params )
1839#endif
1840{
1841#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)))
1842 struct wireless_dev* wdev;
1843#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1844 struct net_device* ndev;
1845#else
1846 int ret;
1847#endif
1848 vos_ssr_protect(__func__);
1849#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1850 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1851 vos_ssr_unprotect(__func__);
1852 return wdev;
1853#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1854 ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1855 vos_ssr_unprotect(__func__);
1856 return ndev;
1857#else
1858 ret = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1859 vos_ssr_unprotect(__func__);
1860 return ret;
1861#endif
1862}
1863
1864#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1865int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1866#else
1867int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001868#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001869{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001870#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1871 struct net_device *dev = wdev->netdev;
1872#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301873 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301874 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301875 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1876 int status;
1877 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001878
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301879 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1880 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1881 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301882 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1883 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001884
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301885 status = wlan_hdd_validate_context(pHddCtx);
1886
1887 if (0 != status)
1888 {
1889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1890 "%s: HDD context is not valid", __func__);
1891 return status;
1892 }
1893
1894 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001895 pVirtAdapter->macAddressCurrent.bytes );
1896
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05301897 hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301898 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1899 EXIT();
1900 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001901}
1902
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301903#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1904int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1905#else
1906int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
1907#endif
1908{
1909 int ret;
1910
1911 vos_ssr_protect(__func__);
1912#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1913 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
1914#else
1915 ret = __wlan_hdd_del_virtual_intf(wiphy, dev);
1916#endif
1917 vos_ssr_unprotect(__func__);
1918
1919 return ret;
1920}
1921
Jeff Johnson295189b2012-06-20 16:38:30 -07001922void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001923 tANI_U32 nFrameLength,
1924 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301925 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07001926{
1927 //Indicate a Frame over Monitor Intf.
1928 int rxstat;
1929 struct sk_buff *skb = NULL;
1930 int needed_headroom = 0;
1931 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1932 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001933#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001934#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1935 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1936#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001937#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001938 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1939
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001940 if (NULL == pbFrames)
1941 {
1942 hddLog(LOGE, FL("NULL frame pointer"));
1943 return;
1944 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001945
1946 /* room for the radiotap header based on driver features
1947 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1948 * RX flags.
1949 * */
1950 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1951
1952 //alloc skb here
1953 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1954 if (unlikely(NULL == skb))
1955 {
1956 hddLog( LOGW, FL("Unable to allocate skb"));
1957 return;
1958 }
1959 skb_reserve(skb, VPKT_SIZE_BUFFER);
1960 if (unlikely(skb_headroom(skb) < nFrameLength))
1961 {
1962 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1963 "HDD [%d]: Insufficient headroom, "
1964 "head[%p], data[%p], req[%d]",
1965 __LINE__, skb->head, skb->data, nFrameLength);
1966 kfree_skb(skb);
1967 return ;
1968 }
1969 // actually push the data
1970 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1971 /* prepend radiotap information */
1972 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1973 {
1974 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1975 //free skb
1976 kfree_skb(skb);
1977 return ;
1978 }
1979
1980 skb_reset_mac_header( skb );
1981 skb->dev = pMonAdapter->dev;
1982 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001983 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001984#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001985#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001986 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001987#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001988#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001989 rxstat = netif_rx_ni(skb);
1990 if( NET_RX_SUCCESS == rxstat )
1991 {
1992 hddLog( LOG1, FL("Success"));
1993 }
1994 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301995 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07001996
1997 return ;
1998}
1999
2000void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302001 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07002002 tANI_U8* pbFrames,
2003 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05302004 tANI_U32 rxChan,
2005 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07002006{
2007 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302008 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07002009 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002010 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07002011 tActionFrmType actionFrmType;
2012 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302013 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05302014 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302015 VOS_STATUS status;
2016 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002017
Arif Hussain6d2a3322013-11-17 19:50:10 -08002018 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002019 __func__, frameType, nFrameLength);
2020
2021 if (NULL == pAdapter)
2022 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002023 hddLog(LOGE, FL("pAdapter is NULL"));
2024 return;
2025 }
2026
2027 if (0 == nFrameLength)
2028 {
2029 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2030 return;
2031 }
2032
2033 if (NULL == pbFrames)
2034 {
2035 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002036 return;
2037 }
2038
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002039 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2040 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2041
2042 /* Get pAdapter from Destination mac address of the frame */
2043 if ((type == SIR_MAC_MGMT_FRAME) &&
2044 (subType != SIR_MAC_MGMT_PROBE_REQ))
2045 {
2046 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
2047 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
2048 if (NULL == pAdapter)
2049 {
2050 /* Under assumtion that we don't receive any action frame
2051 * with BCST as destination we dropping action frame
2052 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08002053 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
2054 MAC_ADDRESS_STR ,
2055 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
2056 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08002057 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002058 return;
2059 }
2060 }
2061
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002062
Jeff Johnson295189b2012-06-20 16:38:30 -07002063 if (NULL == pAdapter->dev)
2064 {
2065 hddLog( LOGE, FL("pAdapter->dev is NULL"));
2066 return;
2067 }
2068
2069 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2070 {
2071 hddLog( LOGE, FL("pAdapter has invalid magic"));
2072 return;
2073 }
2074
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302075 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2076 if (NULL == pHddCtx)
2077 {
2078 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
2079 return;
2080 }
2081
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002082 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2083 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07002084 {
2085 hdd_adapter_t *pMonAdapter =
2086 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
2087
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002088 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07002089 {
2090 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
2091 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
2092 pbFrames, frameType);
2093 return;
2094 }
2095 }
2096
2097 //Channel indicated may be wrong. TODO
2098 //Indicate an action frame.
2099 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
2100 {
2101 freq = ieee80211_channel_to_frequency( rxChan,
2102 IEEE80211_BAND_2GHZ);
2103 }
2104 else
2105 {
2106 freq = ieee80211_channel_to_frequency( rxChan,
2107 IEEE80211_BAND_5GHZ);
2108 }
2109
Jeff Johnsone7245742012-09-05 17:12:55 -07002110 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302111 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302112
2113 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002114 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07002115 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002116 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
2117 {
2118 // public action frame
2119 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08002120 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 -08002121 // P2P action frames
2122 {
2123 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002124 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002125#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002126 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
2127 {
2128 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
2129 actionFrmType);
2130 }
2131 else
2132 {
2133 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
2134 p2p_action_frame_type[actionFrmType]);
2135 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
2136 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2137 {
2138 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
2139 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002140 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002141 }
2142 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
2143 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
2144 {
2145 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08002146 hddLog(LOGE,"[P2P State]GO negotiation progress to "
2147 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002148 }
2149 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
2150 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2151 {
2152 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
2153 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
2154 " completed state Autonomous GO formation");
2155 }
2156 }
2157#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302158 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
2159 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
2160 {
2161 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
2162 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
2163 actionFrmType == WLAN_HDD_INVITATION_REQ ||
2164 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
2165 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
2166 {
2167 hddLog( LOG1, "Extend RoC timer on reception of"
2168 " Action Frame");
2169 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
2170 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
2171 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
2172 else
2173 extend_time = ACTION_FRAME_DEFAULT_WAIT;
2174 if (completion_done(&pAdapter->rem_on_chan_ready_event))
2175 {
2176 vos_timer_stop(
2177 &pRemainChanCtx->hdd_remain_on_chan_timer);
2178 status = vos_timer_start(
2179 &pRemainChanCtx->hdd_remain_on_chan_timer,
2180 extend_time);
2181 if (status != VOS_STATUS_SUCCESS)
2182 {
2183 hddLog( LOGE, "ROC timer start failed");
2184 }
2185 }
2186 else
2187 {
2188 // Buffer Packet
2189 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2190 {
2191 pRemainChanCtx->action_pkt_buff.frame_length =
2192 nFrameLength;
2193 pRemainChanCtx->action_pkt_buff.freq = freq;
2194 pRemainChanCtx->action_pkt_buff.frame_ptr
2195 = vos_mem_malloc(nFrameLength);
2196 vos_mem_copy(
2197 pRemainChanCtx->action_pkt_buff.frame_ptr,
2198 pbFrames, nFrameLength);
2199 hddLog( LOGE,"%s:"
2200 "Action Pkt Cached successfully !!!", __func__);
2201 }
2202 else
2203 {
2204 hddLog( LOGE,"%s:"
2205 "Frames are pending. dropping frame !!!",
2206 __func__);
2207 }
2208 return;
2209 }
2210 }
2211 }
2212 if (pRemainChanCtx != NULL &&
2213 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2214 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2215 hddLog( LOG1, "%s:"
2216 "Rcvd action frame after timer expired ", __func__);
2217
2218 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) ||
2219 (actionFrmType == WLAN_HDD_GO_NEG_REQ) ||
2220 (actionFrmType == WLAN_HDD_INVITATION_REQ) )
2221 {
2222 pScanInfo = &pHddCtx->scan_info;
2223 if((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2224 {
2225 hddLog(LOGE,"Action frame received when Scanning is in"
2226 " progress. Abort Scan.");
2227 hdd_abort_mac_scan(pAdapter->pHddCtx,
2228 pAdapter->sessionId,
2229 eCSR_SCAN_ABORT_DEFAULT);
2230 }
2231 }
2232 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2233 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2234 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2235 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2236 {
2237 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2238 __func__);
2239 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002240 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002241 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002242#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002243 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 -07002244 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002245 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
2246#ifdef WLAN_FEATURE_TDLS_DEBUG
2247 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2248 MAC_ADDR_ARRAY(mac),rxRssi);
2249#endif
2250 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2251 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002252 }
2253#endif
2254 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002255#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002256 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2257 {
2258 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2259 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2260 {
2261 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2262 actionFrmType);
2263 }
2264 else
2265 {
2266 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2267 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002268 }
2269 }
2270#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002271 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2272 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2273 {
Kumar Anand82c009f2014-05-29 00:29:42 -07002274 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
2275 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002276 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002277 }
2278
Jeff Johnson295189b2012-06-20 16:38:30 -07002279 //Indicate Frame Over Normal Interface
2280 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2281
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002282#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2283 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2284 pbFrames, nFrameLength,
2285 GFP_ATOMIC );
2286#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002287 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2288 pbFrames, nFrameLength,
2289 GFP_ATOMIC );
2290#else
2291 cfg80211_rx_mgmt( pAdapter->dev, freq,
2292 pbFrames, nFrameLength,
2293 GFP_ATOMIC );
2294#endif //LINUX_VERSION_CODE
2295}
2296
2297/*
2298 * ieee80211_add_rx_radiotap_header - add radiotap header
2299 */
2300static int hdd_wlan_add_rx_radiotap_hdr (
2301 struct sk_buff *skb, int rtap_len, int flag )
2302{
2303 u8 rtap_temp[20] = {0};
2304 struct ieee80211_radiotap_header *rthdr;
2305 unsigned char *pos;
2306 u16 rx_flags = 0;
2307
2308 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2309
2310 /* radiotap header, set always present flags */
2311 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2312 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2313 rthdr->it_len = cpu_to_le16(rtap_len);
2314
2315 pos = (unsigned char *) (rthdr + 1);
2316
2317 /* the order of the following fields is important */
2318
2319 /* IEEE80211_RADIOTAP_FLAGS */
2320 *pos = 0;
2321 pos++;
2322
2323 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2324 /* ensure 2 byte alignment for the 2 byte field as required */
2325 if ((pos - (u8 *)rthdr) & 1)
2326 pos++;
2327 put_unaligned_le16(rx_flags, pos);
2328 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302329
Jeff Johnson295189b2012-06-20 16:38:30 -07002330 // actually push the data
2331 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2332
2333 return 0;
2334}
2335
2336static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2337 hdd_cfg80211_state_t* cfgState,
2338 tANI_BOOLEAN actionSendSuccess )
2339{
2340 struct ieee80211_radiotap_header *rthdr;
2341 unsigned char *pos;
2342 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002343#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002344#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2345 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2346#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002347#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002348
2349 /* 2 Byte for TX flags and 1 Byte for Retry count */
2350 u32 rtHdrLen = sizeof(*rthdr) + 3;
2351
2352 u8 *data;
2353
2354 /* We have to return skb with Data starting with MAC header. We have
2355 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2356 * entire skb->len from skb and then we will push cfgState->buf to skb
2357 * */
2358 if( NULL == skb_pull(skb, skb->len) )
2359 {
2360 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2361 kfree_skb(cfgState->skb);
2362 return;
2363 }
2364
2365 data = skb_push( skb, cfgState->len );
2366
2367 if (data == NULL)
2368 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002369 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002370 kfree_skb( cfgState->skb );
2371 return;
2372 }
2373
2374 memcpy( data, cfgState->buf, cfgState->len );
2375
2376 /* send frame to monitor interfaces now */
2377 if( skb_headroom(skb) < rtHdrLen )
2378 {
2379 hddLog( LOGE, FL("No headroom for rtap header"));
2380 kfree_skb(cfgState->skb);
2381 return;
2382 }
2383
2384 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2385
2386 memset( rthdr, 0, rtHdrLen );
2387 rthdr->it_len = cpu_to_le16( rtHdrLen );
2388 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2389 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2390 );
2391
2392 pos = (unsigned char *)( rthdr+1 );
2393
2394 // Fill TX flags
2395 *pos = actionSendSuccess;
2396 pos += 2;
2397
2398 // Fill retry count
2399 *pos = 0;
2400 pos++;
2401
2402 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002403 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002404 skb->pkt_type = PACKET_OTHERHOST;
2405 skb->protocol = htons(ETH_P_802_2);
2406 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002407#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002408#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002409 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002410#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002411#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002412 if (in_interrupt())
2413 netif_rx( skb );
2414 else
2415 netif_rx_ni( skb );
2416
2417 /* Enable Queues which we have disabled earlier */
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302418 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002419
2420}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302421