blob: 9bdd32abc65812e88dc5832bef2b5f6cdac8e49a [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**========================================================================
43
44 \file wlan_hdd_p2p.c
45
46 \brief WLAN Host Device Driver implementation for P2P commands interface
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070053
54#include <wlan_hdd_includes.h>
55#include <wlan_hdd_hostapd.h>
56#include <net/cfg80211.h>
57#include "sme_Api.h"
58#include "wlan_hdd_p2p.h"
59#include "sapApi.h"
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053060#include "wlan_hdd_main.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070061
62#include <linux/netdevice.h>
63#include <linux/skbuff.h>
64#include <linux/etherdevice.h>
65#include <net/ieee80211_radiotap.h>
Hoonki Lee1090c6a2013-01-16 17:40:54 -080066#ifdef FEATURE_WLAN_TDLS
67#include "wlan_hdd_tdls.h"
68#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070069
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080070//Ms to Micro Sec
71#define MS_TO_MUS(x) ((x)*1000);
72
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070073#ifdef WLAN_FEATURE_P2P_DEBUG
74#define MAX_P2P_ACTION_FRAME_TYPE 9
75const char *p2p_action_frame_type[]={"GO Negotiation Request",
76 "GO Negotiation Response",
77 "GO Negotiation Confirmation",
78 "P2P Invitation Request",
79 "P2P Invitation Response",
80 "Device Discoverability Request",
81 "Device Discoverability Response",
82 "Provision Discovery Request",
83 "Provision Discovery Response"};
84
85/* We no need to protect this variable since
86 * there is no chance of race to condition
87 * and also not make any complicating the code
88 * just for debugging log
89 */
90tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
91
92#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -080093#ifdef WLAN_FEATURE_TDLS_DEBUG
94#define MAX_TDLS_ACTION_FRAME_TYPE 11
95const char *tdls_action_frame_type[] = {"TDLS Setup Request",
96 "TDLS Setup Response",
97 "TDLS Setup Confirm",
98 "TDLS Teardown",
99 "TDLS Peer Traffic Indication",
100 "TDLS Channel Switch Request",
101 "TDLS Channel Switch Response",
102 "TDLS Peer PSM Request",
103 "TDLS Peer PSM Response",
104 "TDLS Peer Traffic Response",
105 "TDLS Discovery Request" };
106#endif
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700107
Jeff Johnson295189b2012-06-20 16:38:30 -0700108extern struct net_device_ops net_ops_struct;
109
110static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
111 int rtap_len, int flag );
112
113static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
114 hdd_cfg80211_state_t* cfgState,
115 tANI_BOOLEAN actionSendSuccess );
116
117static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
118 tANI_U32 nFrameLength,
119 tANI_U8* pbFrames,
120 tANI_U8 frameType );
121
Jeff Johnson295189b2012-06-20 16:38:30 -0700122eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
123 eHalStatus status )
124{
125 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700126 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
127 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
128
129 if( pRemainChanCtx == NULL )
130 {
131 hddLog( LOGW,
132 "%s: No Rem on channel pending for which Rsp is received", __func__);
133 return eHAL_STATUS_SUCCESS;
134 }
135
136 hddLog( LOG1, "Received remain on channel rsp");
137
138 cfgState->remain_on_chan_ctx = NULL;
139
140 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
141 {
142 if( cfgState->buf )
143 {
144 hddLog( LOGP,
145 "%s: We need to receive yet an ack from one of tx packet",
146 __func__);
147 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800148 cfg80211_remain_on_channel_expired(
149#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
150 pRemainChanCtx->dev->ieee80211_ptr,
151#else
152 pRemainChanCtx->dev,
153#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700154 pRemainChanCtx->cookie,
155 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700156#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
157 pRemainChanCtx->chan_type,
158#endif
159 GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -0700160 }
161
Jeff Johnson295189b2012-06-20 16:38:30 -0700162
163 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700164 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
165 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700166 )
167 {
168 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800169 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
170 {
171 sme_DeregisterMgmtFrame(
172 hHal, sessionId,
173 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
174 NULL, 0 );
175 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700176 }
177 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
178 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
179 )
180 {
181 WLANSAP_DeRegisterMgmtFrame(
182 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
183 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
184 NULL, 0 );
185 }
186
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800187 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800188 pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700189 complete(&pAdapter->cancel_rem_on_chan_var);
190 return eHAL_STATUS_SUCCESS;
191}
192
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -0800193void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700194{
Jeff Johnson295189b2012-06-20 16:38:30 -0700195 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
196 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700197
Jeff Johnson32d95a32012-09-10 13:15:23 -0700198 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700199 {
Jeff Johnson32d95a32012-09-10 13:15:23 -0700200 hddLog( LOG1, "Cancel Existing Remain on Channel");
201
202 /* Wait till remain on channel ready indication before issuing cancel
203 * remain on channel request, otherwise if remain on channel not
204 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700205 * will be in unknown state.
206 */
207 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
208 msecs_to_jiffies(WAIT_REM_CHAN_READY));
209 if (!status)
210 {
211 hddLog( LOGE,
212 "%s: timeout waiting for remain on channel ready indication",
213 __func__);
214 }
215
216 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700217
Jeff Johnson295189b2012-06-20 16:38:30 -0700218 /* Issue abort remain on chan request to sme.
219 * The remain on channel callback will make sure the remain_on_chan
220 * expired event is sent.
221 */
222 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700223 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
224 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 )
226 {
227 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
228 pAdapter->sessionId );
229 }
230 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
231 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
232 )
233 {
234 WLANSAP_CancelRemainOnChannel(
235 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
236 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700237
Jeff Johnson32d95a32012-09-10 13:15:23 -0700238 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700239 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700240
241 if (!status)
242 {
243 hddLog( LOGE,
244 "%s: timeout waiting for cancel remain on channel ready indication",
245 __func__);
246 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700247 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700248}
249
250int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
251{
252 int status = 0;
253 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
254
255 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
256 {
257 //Cancel Existing Remain On Channel
258 //If no action frame is pending
259 if( cfgState->remain_on_chan_ctx != NULL)
260 {
261 //Check whether Action Frame is pending or not
262 if( cfgState->buf == NULL)
263 {
264 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
265 }
266 else
267 {
268 hddLog( LOG1, "Cannot Cancel Existing Remain on Channel");
269 status = -EBUSY;
270 }
271 }
272 }
273 return status;
274}
275
276static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
277 struct net_device *dev,
278 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700279#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700280 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700281#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700282 unsigned int duration, u64 *cookie,
283 rem_on_channel_request_type_t request_type )
284{
285 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
286 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
287 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
288 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
289 __func__,pAdapter->device_mode);
290
Yue Maf49ba872013-08-19 12:04:25 -0700291#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700292 hddLog( LOG1,
293 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d",
294 chan->hw_value, chan->center_freq, channel_type, duration );
Yue Maf49ba872013-08-19 12:04:25 -0700295#else
296 hddLog( LOG1,
297 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d",
298 chan->hw_value, chan->center_freq, duration );
299#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700300 //Cancel existing remain On Channel if any
301 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700302
Jeff Johnsone7245742012-09-05 17:12:55 -0700303 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700304 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700305 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700306 * channel requets when Load/Unload is in progress*/
307 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
308 {
309 hddLog( LOGE,
310 "%s: Wlan Load/Unload is in progress", __func__);
311 return -EBUSY;
312 }
313
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700314 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
315 {
316 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
317 "%s:LOGP in Progress. Ignore!!!", __func__);
318 return -EAGAIN;
319 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700320 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
321 if( NULL == pRemainChanCtx )
322 {
323 hddLog(VOS_TRACE_LEVEL_FATAL,
324 "%s: Not able to allocate memory for Channel context",
325 __func__);
326 return -ENOMEM;
327 }
328
329 vos_mem_copy( &pRemainChanCtx->chan, chan,
330 sizeof(struct ieee80211_channel) );
331
Yue Maf49ba872013-08-19 12:04:25 -0700332#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700333 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700334#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700335 pRemainChanCtx->duration = duration;
336 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800337 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700338 pRemainChanCtx->cookie = *cookie;
339 pRemainChanCtx->rem_on_chan_request = request_type;
340 cfgState->remain_on_chan_ctx = pRemainChanCtx;
341 cfgState->current_freq = chan->center_freq;
342
343 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
344
345 //call sme API to start remain on channel.
346 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700347 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
348 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700349 )
350 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700351 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700352 //call sme API to start remain on channel.
353 sme_RemainOnChannel(
354 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
355 chan->hw_value, duration,
Gopichand Nakkala924e4552013-05-08 19:18:14 +0530356 wlan_hdd_remain_on_channel_callback, pAdapter,
357 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700358
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800359 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
360 {
361 sme_RegisterMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
362 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
363 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 );
364 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700365
366 }
367 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
368 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
369 )
370 {
371 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700372 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700373 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
374 chan->hw_value, duration,
375 wlan_hdd_remain_on_channel_callback, pAdapter ))
376
377 {
378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
379 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
380 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700381 vos_mem_free (pRemainChanCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700382 return -EINVAL;
383 }
384
385
Jeff Johnson43971f52012-07-17 12:26:56 -0700386 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700387 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
388 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
389 NULL, 0 ))
390 {
391 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
392 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
393 WLANSAP_CancelRemainOnChannel(
394 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
395 return -EINVAL;
396 }
397
398 }
399 return 0;
400
401}
402
403int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800404#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
405 struct wireless_dev *wdev,
406#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700407 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800408#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700409 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700410#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700411 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700412#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700413 unsigned int duration, u64 *cookie )
414{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800415#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
416 struct net_device *dev = wdev->netdev;
417#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700418 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700419 chan,
420#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
421 channel_type,
422#endif
423 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700424 REMAIN_ON_CHANNEL_REQUEST);
425}
426
427void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
428{
429 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
430 hdd_remain_on_chan_ctx_t* pRemainChanCtx = cfgState->remain_on_chan_ctx;
431
432 hddLog( LOG1, "Ready on chan ind");
433
434 if( pRemainChanCtx != NULL )
435 {
436 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
437 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800438 cfg80211_ready_on_channel(
439#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
440 pAdapter->dev->ieee80211_ptr,
441#else
442 pAdapter->dev,
443#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800444 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700445 &pRemainChanCtx->chan,
446#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
447 pRemainChanCtx->chan_type,
448#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700449 pRemainChanCtx->duration, GFP_KERNEL );
450 }
451#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
452 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request )
453 {
454 complete(&pAdapter->offchannel_tx_event);
455 }
456#endif
457 complete(&pAdapter->rem_on_chan_ready_event);
458 }
459 else
460 {
461 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
462 }
463 return;
464}
465
466int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800467#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
468 struct wireless_dev *wdev,
469#else
470 struct net_device *dev,
471#endif
472 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700473{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800474#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
475 struct net_device *dev = wdev->netdev;
476#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700477 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700478 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530479 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
480 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700481
482 hddLog( LOG1, "Cancel remain on channel req");
483
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530484 status = wlan_hdd_validate_context(pHddCtx);
485
486 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700487 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530488 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
489 "%s: HDD context is not valid", __func__);
490 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700491 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700492 /* FIXME cancel currently running remain on chan.
493 * Need to check cookie and cancel accordingly
494 */
495 if( (cfgState->remain_on_chan_ctx == NULL) ||
496 (cfgState->remain_on_chan_ctx->cookie != cookie) )
497 {
498 hddLog( LOGE,
499 "%s: No Remain on channel pending with specified cookie value",
500 __func__);
501 return -EINVAL;
502 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530503
504 /* wait until remain on channel ready event received
Jeff Johnson295189b2012-06-20 16:38:30 -0700505 * for already issued remain on channel request */
506 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
507 msecs_to_jiffies(WAIT_REM_CHAN_READY));
508 if (!status)
509 {
510 hddLog( LOGE,
511 "%s: timeout waiting for remain on channel ready indication",
512 __func__);
513 }
514 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
515 /* Issue abort remain on chan request to sme.
516 * The remain on channel callback will make sure the remain_on_chan
517 * expired event is sent.
518 */
519 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700520 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
521 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700522 )
523 {
524 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700525 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
526 sessionId );
527 }
528 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
529 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
530 )
531 {
532 WLANSAP_CancelRemainOnChannel(
533 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
534 }
535 else
536 {
537 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
538 __func__, pAdapter->device_mode);
539 return -EIO;
540 }
541 wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
542 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
543 return 0;
544}
545
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800546#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
547int wlan_hdd_action( struct wiphy *wiphy, struct wireless_dev *wdev,
548 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700549#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800550 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700551 bool channel_type_valid,
552#endif
553 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800554 const u8 *buf, size_t len, bool no_cck,
555 bool dont_wait_for_ack, u64 *cookie )
556#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700557int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
558 struct ieee80211_channel *chan, bool offchan,
559 enum nl80211_channel_type channel_type,
560 bool channel_type_valid, unsigned int wait,
561 const u8 *buf, size_t len, bool no_cck,
562 bool dont_wait_for_ack, u64 *cookie )
563#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
564int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
565 struct ieee80211_channel *chan, bool offchan,
566 enum nl80211_channel_type channel_type,
567 bool channel_type_valid, unsigned int wait,
568 const u8 *buf, size_t len, u64 *cookie )
569#else
570int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
571 struct ieee80211_channel *chan,
572 enum nl80211_channel_type channel_type,
573 bool channel_type_valid,
574 const u8 *buf, size_t len, u64 *cookie )
575#endif //LINUX_VERSION_CODE
576{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800577#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
578 struct net_device *dev = wdev->netdev;
579#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700580 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
581 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530582 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700583 tANI_U16 extendedWait = 0;
584 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
585 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
586 tActionFrmType actionFrmType;
587 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530588 int status;
Chet Lanctot186b5732013-03-18 10:26:30 -0700589#ifdef WLAN_FEATURE_11W
590 tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit
591#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700592
Jeff Johnson295189b2012-06-20 16:38:30 -0700593#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
594 hdd_adapter_t *goAdapter;
595#endif
596
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530597 status = wlan_hdd_validate_context(pHddCtx);
598
599 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800600 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
602 "%s: HDD context is not valid", __func__);
603 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800604 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530605
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700606#ifdef WLAN_FEATURE_P2P_DEBUG
607 if ((type == SIR_MAC_MGMT_FRAME) &&
608 (subType == SIR_MAC_MGMT_ACTION) &&
609 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
610 {
611 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800612 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700613 {
614 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
615 actionFrmType);
616 }
617 else
618 {
619 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
620 p2p_action_frame_type[actionFrmType]);
621 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
622 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
623 {
624 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
625 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800626 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700627 }
628 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
629 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
630 {
631 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
632 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
633 " completed state");
634 }
635 }
636 }
637#endif
638
Jeff Johnsone7245742012-09-05 17:12:55 -0700639#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
640 noack = dont_wait_for_ack;
641#endif
642
643 //If the wait is coming as 0 with off channel set
644 //then set the wait to 200 ms
645 if (offchan && !wait)
646 wait = ACTION_FRAME_DEFAULT_WAIT;
647
Jeff Johnson295189b2012-06-20 16:38:30 -0700648 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
649 __func__,pAdapter->device_mode);
650
651 //Call sme API to send out a action frame.
652 // OR can we send it directly through data path??
653 // After tx completion send tx status back.
654 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
655 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
656 )
657 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700658 if (type == SIR_MAC_MGMT_FRAME)
659 {
660 if (subType == SIR_MAC_MGMT_PROBE_RSP)
661 {
662 /* Drop Probe response recieved from supplicant, as for GO and
663 SAP PE itself sends probe response
664 */
665 goto err_rem_channel;
666 }
667 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
668 (subType == SIR_MAC_MGMT_DEAUTH))
669 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700670 /* During EAP failure or P2P Group Remove supplicant
671 * is sending del_station command to driver. From
672 * del_station function, Driver will send deauth frame to
673 * p2p client. No need to send disassoc frame from here.
674 * so Drop the frame here and send tx indication back to
675 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700676 */
677 tANI_U8 dstMac[ETH_ALEN] = {0};
678 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700679 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700680 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -0800681 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -0700682 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -0800683 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700684 goto err_rem_channel;
685 }
686 }
687 }
688
689 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800690 {
691 if ( !noack )
692 {
693 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
694 __func__);
695 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
696 }
697 else
698 {
699 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
700 __func__);
701 return -EBUSY;
702 }
703 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700704
705 hddLog( LOG1, "Action frame tx request");
706
707#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
708 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
709
710 //If GO adapter exists and operating on same frequency
711 //then we will not request remain on channel
712 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
713 == goAdapter->sessionCtx.ap.operatingChannel ) )
714 {
715 goto send_frame;
716 }
717#endif
718
719#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
720 if( offchan && wait)
721 {
722 int status;
723
724 // In case of P2P Client mode if we are already
725 // on the same channel then send the frame directly
726
727 if((cfgState->remain_on_chan_ctx != NULL) &&
728 (cfgState->current_freq == chan->center_freq)
729 )
730 {
Arif Hussain6d2a3322013-11-17 19:50:10 -0800731 hddLog(LOG1,"action frame: extending the wait time");
Jeff Johnsone7245742012-09-05 17:12:55 -0700732 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700733 goto send_frame;
734 }
Agarwal Ashish963bf002013-12-10 16:57:10 +0530735
Jeff Johnson295189b2012-06-20 16:38:30 -0700736 INIT_COMPLETION(pAdapter->offchannel_tx_event);
737
738 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700739 chan,
740#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
741 channel_type,
742#endif
743 wait, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700744 OFF_CHANNEL_ACTION_TX);
745
746 if(0 != status)
747 {
748 if( (-EBUSY == status) &&
749 (cfgState->current_freq == chan->center_freq) )
750 {
751 goto send_frame;
752 }
753 goto err_rem_channel;
754 }
Madan Mohan Koyyalamudi87673f62013-09-27 02:39:27 +0530755 /* This will extend timer in LIM when sending Any action frame
756 * It will cover remain on channel timer till next action frame
757 * in rx direction.
758 */
759 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700760 /* Wait for driver to be ready on the requested channel */
761 status = wait_for_completion_interruptible_timeout(
762 &pAdapter->offchannel_tx_event,
763 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
764 if(!status)
765 {
766 hddLog( LOGE, "Not able to complete remain on channel request"
767 " within timeout period");
768 goto err_rem_channel;
769 }
770 }
771 else if ( offchan )
772 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700773 /* Check before sending action frame
774 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -0700775 if(NULL == cfgState->remain_on_chan_ctx)
776 {
777 goto err_rem_channel;
778 }
779 }
780 send_frame:
781#endif
782
Jeff Johnsone7245742012-09-05 17:12:55 -0700783 if(!noack)
784 {
785 cfgState->buf = vos_mem_malloc( len ); //buf;
786 if( cfgState->buf == NULL )
787 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -0700788
Jeff Johnsone7245742012-09-05 17:12:55 -0700789 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -0700790
Jeff Johnsone7245742012-09-05 17:12:55 -0700791 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700792
793#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700794 if( cfgState->remain_on_chan_ctx )
795 {
796 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
797 *cookie = cfgState->action_cookie;
798 }
799 else
800 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700801#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800802 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -0700803 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -0700804#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700805 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700806#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700807 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700808
809 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700810 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
811 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700812 )
813 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700814 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800815
Jeff Johnsone7245742012-09-05 17:12:55 -0700816 if ((type == SIR_MAC_MGMT_FRAME) &&
817 (subType == SIR_MAC_MGMT_ACTION) &&
818 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -0700819 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700820 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -0800821 hddLog(LOG1, "Tx Action Frame %u", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -0700822 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -0700823 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700824 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Arif Hussain6d2a3322013-11-17 19:50:10 -0800825 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -0700826 }
827 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
828 {
829 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Arif Hussain6d2a3322013-11-17 19:50:10 -0800830 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700831 }
832 }
Chet Lanctot186b5732013-03-18 10:26:30 -0700833#ifdef WLAN_FEATURE_11W
834 if ((type == SIR_MAC_MGMT_FRAME) &&
835 (subType == SIR_MAC_MGMT_ACTION) &&
836 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME))
837 {
838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
839 "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query");
840 // Since this is an SA Query Action Frame, we have to protect it
841 WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]);
842 }
843#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700844 if (eHAL_STATUS_SUCCESS !=
845 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -0700846 sessionId, buf, len, extendedWait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -0700847 {
848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
849 "%s: sme_sendAction returned fail", __func__);
850 goto err;
851 }
852 }
853 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
854 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
855 )
856 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700857 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700858 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700859 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700860 {
861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
862 "%s: WLANSAP_SendAction returned fail", __func__);
863 goto err;
864 }
865 }
866
867 return 0;
868err:
Jeff Johnsone7245742012-09-05 17:12:55 -0700869 if(!noack)
870 {
871 hdd_sendActionCnf( pAdapter, FALSE );
872 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700873 return 0;
874err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800875 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800876 cfg80211_mgmt_tx_status(
877#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
878 pAdapter->dev->ieee80211_ptr,
879#else
880 pAdapter->dev,
881#endif
882 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -0700883 return 0;
884}
885
886#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800887#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
888int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
889 struct wireless_dev *wdev,
890 u64 cookie)
891{
892 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
893}
894#else
895int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -0700896 struct net_device *dev,
897 u64 cookie)
898{
899 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
900}
901#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800902#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700903
904void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
905{
906 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
907
Jeff Johnsone7245742012-09-05 17:12:55 -0700908 cfgState->actionFrmState = HDD_IDLE;
909
Jeff Johnson295189b2012-06-20 16:38:30 -0700910 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
911 if( NULL == cfgState->buf )
912 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700913 return;
914 }
915
916 /* If skb is NULL it means this packet was received on CFG80211 interface
917 * else it was received on Monitor interface */
918 if( cfgState->skb == NULL )
919 {
920 /*
921 * buf is the same pointer it passed us to send. Since we are sending
922 * it through control path, we use different buffers.
923 * In case of mac80211, they just push it to the skb and pass the same
924 * data while sending tx ack status.
925 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800926 cfg80211_mgmt_tx_status(
927#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
928 pAdapter->dev->ieee80211_ptr,
929#else
930 pAdapter->dev,
931#endif
932 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
934 vos_mem_free( cfgState->buf );
935 cfgState->buf = NULL;
936 }
937 else
938 {
939 hdd_adapter_t* pMonAdapter =
940 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
941 if( pMonAdapter == NULL )
942 {
943 hddLog( LOGE, "Not able to get Monitor Adapter");
944 cfgState->skb = NULL;
945 vos_mem_free( cfgState->buf );
946 cfgState->buf = NULL;
947 complete(&pAdapter->tx_action_cnf_event);
948 return;
949 }
950 /* Send TX completion feedback over monitor interface. */
951 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
952 cfgState->skb = NULL;
953 vos_mem_free( cfgState->buf );
954 cfgState->buf = NULL;
955 /* Look for the next Mgmt packet to TX */
956 hdd_mon_tx_mgmt_pkt(pAdapter);
957 }
958 complete(&pAdapter->tx_action_cnf_event);
959}
960
961/**
962 * hdd_setP2pNoa
963 *
964 *FUNCTION:
965 * This function is called from hdd_hostapd_ioctl function when Driver
966 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
967 *
968 *LOGIC:
969 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
970 *
971 *ASSUMPTIONS:
972 *
973 *
974 *NOTE:
975 *
976 * @param dev Pointer to net device structure
977 * @param command Pointer to command
978 *
979 * @return Status
980 */
981
982int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
983{
984 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
985 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
986 VOS_STATUS status = VOS_STATUS_SUCCESS;
987 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800988 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -0700989 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -0800990 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700991
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -0800992 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800994 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -0800996 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
997 if (ret < 3)
998 {
999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1000 "%s: P2P_SET GO NoA: fail to read param "
1001 "count=%d duration=%d interval=%d \n",
1002 __func__, count, start_time, duration);
1003 return -EINVAL;
1004 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001006 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001007 __func__, count, start_time, duration);
1008 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001009 /* PS Selection
1010 * Periodic NoA (2)
1011 * Single NOA (4)
1012 */
1013 NoA.opp_ps = 0;
1014 NoA.ctWindow = 0;
1015 if (count == 1)
1016 {
1017 NoA.duration = 0;
1018 NoA.single_noa_duration = duration;
1019 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1020 }
1021 else
1022 {
1023 NoA.duration = duration;
1024 NoA.single_noa_duration = 0;
1025 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1026 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001027 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001028 NoA.count = count;
1029 NoA.sessionid = pAdapter->sessionId;
1030
1031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1032 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1033 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001034 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001035 NoA.ctWindow, NoA.duration, NoA.interval,
1036 NoA.count, NoA.single_noa_duration,
1037 NoA.psSelection);
1038
1039 sme_p2pSetPs(hHal, &NoA);
1040 return status;
1041}
1042
1043/**
1044 * hdd_setP2pOpps
1045 *
1046 *FUNCTION:
1047 * This function is called from hdd_hostapd_ioctl function when Driver
1048 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1049 *
1050 *LOGIC:
1051 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1052 *
1053 *ASSUMPTIONS:
1054 *
1055 *
1056 *NOTE:
1057 *
1058 * @param dev Pointer to net device structure
1059 * @param command Pointer to command
1060 *
1061 * @return Status
1062 */
1063
1064int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1065{
1066 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1067 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1068 VOS_STATUS status = VOS_STATUS_SUCCESS;
1069 tP2pPsConfig NoA;
1070 char *param;
1071 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001072 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001073
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001074 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001075 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001076 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001077 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001078 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1079 if (ret < 3)
1080 {
1081 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1082 "%s: P2P_SET GO PS: fail to read param "
1083 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1084 __func__, legacy_ps, opp_ps, ctwindow);
1085 return -EINVAL;
1086 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001087 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001088 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001089 __func__, legacy_ps, opp_ps, ctwindow);
1090
1091 /* PS Selection
1092 * Opportunistic Power Save (1)
1093 */
1094
1095 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1096 * When user want to set ctWindow during that time other parameters
1097 * values are coming from wpa_supplicant as -1.
1098 * Example : User want to set ctWindow with 30 then wpa_cli command :
1099 * P2P_SET ctwindow 30
1100 * Command Received at hdd_hostapd_ioctl is as below:
1101 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
1102 */
1103 if (ctwindow != -1)
1104 {
1105
1106 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001107 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1109
1110 if (ctwindow != pAdapter->ctw)
1111 {
1112 pAdapter->ctw = ctwindow;
1113
1114 if(pAdapter->ops)
1115 {
1116 NoA.opp_ps = pAdapter->ops;
1117 NoA.ctWindow = pAdapter->ctw;
1118 NoA.duration = 0;
1119 NoA.single_noa_duration = 0;
1120 NoA.interval = 0;
1121 NoA.count = 0;
1122 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1123 NoA.sessionid = pAdapter->sessionId;
1124
1125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1126 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1127 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001128 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001129 NoA.ctWindow, NoA.duration, NoA.interval,
1130 NoA.count, NoA.single_noa_duration,
1131 NoA.psSelection);
1132
1133 sme_p2pSetPs(hHal, &NoA);
1134 }
1135 return 0;
1136 }
1137 }
1138
1139 if (opp_ps != -1)
1140 {
1141 pAdapter->ops = opp_ps;
1142
1143 if ((opp_ps != -1) && (pAdapter->ctw))
1144 {
1145 NoA.opp_ps = opp_ps;
1146 NoA.ctWindow = pAdapter->ctw;
1147 NoA.duration = 0;
1148 NoA.single_noa_duration = 0;
1149 NoA.interval = 0;
1150 NoA.count = 0;
1151 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1152 NoA.sessionid = pAdapter->sessionId;
1153
1154 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1155 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1156 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001157 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001158 NoA.ctWindow, NoA.duration, NoA.interval,
1159 NoA.count, NoA.single_noa_duration,
1160 NoA.psSelection);
1161
1162 sme_p2pSetPs(hHal, &NoA);
1163 }
1164 }
1165 return status;
1166}
1167
1168int hdd_setP2pPs( struct net_device *dev, void *msgData )
1169{
1170 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1171 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1172 VOS_STATUS status = VOS_STATUS_SUCCESS;
1173 tP2pPsConfig NoA;
1174 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1175
1176 NoA.opp_ps = pappNoA->opp_ps;
1177 NoA.ctWindow = pappNoA->ctWindow;
1178 NoA.duration = pappNoA->duration;
1179 NoA.interval = pappNoA->interval;
1180 NoA.count = pappNoA->count;
1181 NoA.single_noa_duration = pappNoA->single_noa_duration;
1182 NoA.psSelection = pappNoA->psSelection;
1183 NoA.sessionid = pAdapter->sessionId;
1184
1185 sme_p2pSetPs(hHal, &NoA);
1186 return status;
1187}
Jeff Johnson295189b2012-06-20 16:38:30 -07001188
1189static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1190{
1191 tANI_U8 sessionType;
1192
1193 switch( type )
1194 {
1195 case NL80211_IFTYPE_AP:
1196 sessionType = WLAN_HDD_SOFTAP;
1197 break;
1198 case NL80211_IFTYPE_P2P_GO:
1199 sessionType = WLAN_HDD_P2P_GO;
1200 break;
1201 case NL80211_IFTYPE_P2P_CLIENT:
1202 sessionType = WLAN_HDD_P2P_CLIENT;
1203 break;
1204 case NL80211_IFTYPE_STATION:
1205 sessionType = WLAN_HDD_INFRA_STATION;
1206 break;
1207 case NL80211_IFTYPE_MONITOR:
1208 sessionType = WLAN_HDD_MONITOR;
1209 break;
1210 default:
1211 sessionType = WLAN_HDD_INFRA_STATION;
1212 break;
1213 }
1214
1215 return sessionType;
1216}
1217
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001218#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1219struct wireless_dev* wlan_hdd_add_virtual_intf(
1220 struct wiphy *wiphy, const char *name,
1221 enum nl80211_iftype type,
1222 u32 *flags, struct vif_params *params )
1223#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1224struct wireless_dev* wlan_hdd_add_virtual_intf(
1225 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1226 u32 *flags, struct vif_params *params )
1227#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001228struct net_device* wlan_hdd_add_virtual_intf(
1229 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1230 u32 *flags, struct vif_params *params )
1231#else
1232int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1233 enum nl80211_iftype type,
1234 u32 *flags, struct vif_params *params )
1235#endif
1236{
1237 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1238 hdd_adapter_t* pAdapter = NULL;
1239
1240 ENTER();
1241
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001242 if(hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
1243 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001244 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001245 "interfaces of same type are not supported currently.",__func__, type);
Jeff Johnsond13512a2012-07-17 11:42:19 -07001246 return NULL;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001247 }
1248
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001249 if (pHddCtx->isLogpInProgress)
1250 {
1251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1252 "%s:LOGP in Progress. Ignore!!!", __func__);
1253#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1254 return NULL;
1255#else
1256 return -EAGAIN;
1257#endif
1258 }
Kiet Lam04e26912013-10-18 20:13:38 +05301259 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1260 ((NL80211_IFTYPE_P2P_GO == type) ||
1261 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001262 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001263 /* Generate the P2P Interface Address. this address must be
1264 * different from the P2P Device Address.
1265 */
1266 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1267 p2pDeviceAddress.bytes[4] ^= 0x80;
1268 pAdapter = hdd_open_adapter( pHddCtx,
1269 wlan_hdd_get_session_type(type),
1270 name, p2pDeviceAddress.bytes,
1271 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001272 }
1273 else
1274 {
1275 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1276 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1277 }
1278
1279 if( NULL == pAdapter)
1280 {
1281 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1282#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1283 return NULL;
1284#else
1285 return -EINVAL;
1286#endif
1287 }
1288 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001289#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1290 return pAdapter->dev->ieee80211_ptr;
1291#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001292 return pAdapter->dev;
1293#else
1294 return 0;
1295#endif
1296}
1297
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001298#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1299int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1300#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001301int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001302#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001303{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001304#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1305 struct net_device *dev = wdev->netdev;
1306#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301307 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1308 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1309 int status;
1310 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001311
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301312 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1313 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001314
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301315 status = wlan_hdd_validate_context(pHddCtx);
1316
1317 if (0 != status)
1318 {
1319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1320 "%s: HDD context is not valid", __func__);
1321 return status;
1322 }
1323
1324 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001325 pVirtAdapter->macAddressCurrent.bytes );
1326
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301327 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1328 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1329 EXIT();
1330 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001331}
1332
1333void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001334 tANI_U32 nFrameLength,
1335 tANI_U8* pbFrames,
Jeff Johnson295189b2012-06-20 16:38:30 -07001336 tANI_U8 frameType )
1337{
1338 //Indicate a Frame over Monitor Intf.
1339 int rxstat;
1340 struct sk_buff *skb = NULL;
1341 int needed_headroom = 0;
1342 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1343 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001344#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001345#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1346 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1347#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001348#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001349 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1350
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001351 if (NULL == pbFrames)
1352 {
1353 hddLog(LOGE, FL("NULL frame pointer"));
1354 return;
1355 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001356
1357 /* room for the radiotap header based on driver features
1358 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1359 * RX flags.
1360 * */
1361 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1362
1363 //alloc skb here
1364 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1365 if (unlikely(NULL == skb))
1366 {
1367 hddLog( LOGW, FL("Unable to allocate skb"));
1368 return;
1369 }
1370 skb_reserve(skb, VPKT_SIZE_BUFFER);
1371 if (unlikely(skb_headroom(skb) < nFrameLength))
1372 {
1373 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1374 "HDD [%d]: Insufficient headroom, "
1375 "head[%p], data[%p], req[%d]",
1376 __LINE__, skb->head, skb->data, nFrameLength);
1377 kfree_skb(skb);
1378 return ;
1379 }
1380 // actually push the data
1381 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1382 /* prepend radiotap information */
1383 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1384 {
1385 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1386 //free skb
1387 kfree_skb(skb);
1388 return ;
1389 }
1390
1391 skb_reset_mac_header( skb );
1392 skb->dev = pMonAdapter->dev;
1393 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001394 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001395#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001396#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001397 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001398#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001399#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001400 rxstat = netif_rx_ni(skb);
1401 if( NET_RX_SUCCESS == rxstat )
1402 {
1403 hddLog( LOG1, FL("Success"));
1404 }
1405 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301406 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07001407
1408 return ;
1409}
1410
1411void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
1412 tANI_U32 nFrameLength,
1413 tANI_U8* pbFrames,
1414 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301415 tANI_U32 rxChan,
1416 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001417{
1418 tANI_U16 freq;
Jeff Johnsone7245742012-09-05 17:12:55 -07001419 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001420 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001421 tActionFrmType actionFrmType;
1422 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301423 hdd_context_t *pHddCtx = NULL;
1424 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001425
Arif Hussain6d2a3322013-11-17 19:50:10 -08001426 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001427 __func__, frameType, nFrameLength);
1428
1429 if (NULL == pAdapter)
1430 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001431 hddLog(LOGE, FL("pAdapter is NULL"));
1432 return;
1433 }
1434
1435 if (0 == nFrameLength)
1436 {
1437 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
1438 return;
1439 }
1440
1441 if (NULL == pbFrames)
1442 {
1443 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001444 return;
1445 }
1446
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001447 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1448 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1449
1450 /* Get pAdapter from Destination mac address of the frame */
1451 if ((type == SIR_MAC_MGMT_FRAME) &&
1452 (subType != SIR_MAC_MGMT_PROBE_REQ))
1453 {
1454 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1455 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1456 if (NULL == pAdapter)
1457 {
1458 /* Under assumtion that we don't receive any action frame
1459 * with BCST as destination we dropping action frame
1460 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001461 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1462 MAC_ADDRESS_STR ,
1463 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1464 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08001465 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001466 return;
1467 }
1468 }
1469
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001470
Jeff Johnson295189b2012-06-20 16:38:30 -07001471 if (NULL == pAdapter->dev)
1472 {
1473 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1474 return;
1475 }
1476
1477 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1478 {
1479 hddLog( LOGE, FL("pAdapter has invalid magic"));
1480 return;
1481 }
1482
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301483 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1484 if (NULL == pHddCtx)
1485 {
1486 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
1487 return;
1488 }
1489
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001490 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1491 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001492 {
1493 hdd_adapter_t *pMonAdapter =
1494 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1495
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001496 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001497 {
1498 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1499 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1500 pbFrames, frameType);
1501 return;
1502 }
1503 }
1504
1505 //Channel indicated may be wrong. TODO
1506 //Indicate an action frame.
1507 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1508 {
1509 freq = ieee80211_channel_to_frequency( rxChan,
1510 IEEE80211_BAND_2GHZ);
1511 }
1512 else
1513 {
1514 freq = ieee80211_channel_to_frequency( rxChan,
1515 IEEE80211_BAND_5GHZ);
1516 }
1517
Jeff Johnsone7245742012-09-05 17:12:55 -07001518 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1519
1520 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001521 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001522 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001523 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1524 {
1525 // public action frame
1526 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001527 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 -08001528 // P2P action frames
1529 {
1530 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08001531 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001532#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001533 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1534 {
1535 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1536 actionFrmType);
1537 }
1538 else
1539 {
1540 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1541 p2p_action_frame_type[actionFrmType]);
1542 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1543 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1544 {
1545 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1546 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001547 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001548 }
1549 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1550 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1551 {
1552 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001553 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1554 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001555 }
1556 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1557 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1558 {
1559 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1560 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1561 " completed state Autonomous GO formation");
1562 }
1563 }
1564#endif
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301565 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) ||
1566 (actionFrmType == WLAN_HDD_GO_NEG_REQ) )
1567 {
1568 pScanInfo = &pHddCtx->scan_info;
1569 if((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
1570 {
1571 hddLog(LOGE,"Action frame received when Scanning is in"
1572 " progress. Abort Scan.");
1573 hdd_abort_mac_scan(pAdapter->pHddCtx,
1574 pAdapter->sessionId);
1575 }
1576 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001577 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
1578 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
1579 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
1580 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
1581 {
1582 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
1583 __func__);
1584 hdd_sendActionCnf(pAdapter, TRUE);
1585 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001586 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001587#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001588 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 -07001589 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001590 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
1591#ifdef WLAN_FEATURE_TDLS_DEBUG
1592 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
1593 MAC_ADDR_ARRAY(mac),rxRssi);
1594#endif
1595 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
1596 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001597 }
1598#endif
1599 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001600#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001601 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
1602 {
1603 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
1604 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
1605 {
1606 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
1607 actionFrmType);
1608 }
1609 else
1610 {
1611 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
1612 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001613 }
1614 }
1615#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07001616 }
1617
Jeff Johnson295189b2012-06-20 16:38:30 -07001618 //Indicate Frame Over Normal Interface
1619 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
1620
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001621#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1622 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
1623 pbFrames, nFrameLength,
1624 GFP_ATOMIC );
1625#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001626 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
1627 pbFrames, nFrameLength,
1628 GFP_ATOMIC );
1629#else
1630 cfg80211_rx_mgmt( pAdapter->dev, freq,
1631 pbFrames, nFrameLength,
1632 GFP_ATOMIC );
1633#endif //LINUX_VERSION_CODE
1634}
1635
1636/*
1637 * ieee80211_add_rx_radiotap_header - add radiotap header
1638 */
1639static int hdd_wlan_add_rx_radiotap_hdr (
1640 struct sk_buff *skb, int rtap_len, int flag )
1641{
1642 u8 rtap_temp[20] = {0};
1643 struct ieee80211_radiotap_header *rthdr;
1644 unsigned char *pos;
1645 u16 rx_flags = 0;
1646
1647 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
1648
1649 /* radiotap header, set always present flags */
1650 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
1651 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
1652 rthdr->it_len = cpu_to_le16(rtap_len);
1653
1654 pos = (unsigned char *) (rthdr + 1);
1655
1656 /* the order of the following fields is important */
1657
1658 /* IEEE80211_RADIOTAP_FLAGS */
1659 *pos = 0;
1660 pos++;
1661
1662 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
1663 /* ensure 2 byte alignment for the 2 byte field as required */
1664 if ((pos - (u8 *)rthdr) & 1)
1665 pos++;
1666 put_unaligned_le16(rx_flags, pos);
1667 pos += 2;
1668
1669 // actually push the data
1670 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
1671
1672 return 0;
1673}
1674
1675static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
1676 hdd_cfg80211_state_t* cfgState,
1677 tANI_BOOLEAN actionSendSuccess )
1678{
1679 struct ieee80211_radiotap_header *rthdr;
1680 unsigned char *pos;
1681 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001682#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001683#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1684 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
1685#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001686#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001687
1688 /* 2 Byte for TX flags and 1 Byte for Retry count */
1689 u32 rtHdrLen = sizeof(*rthdr) + 3;
1690
1691 u8 *data;
1692
1693 /* We have to return skb with Data starting with MAC header. We have
1694 * copied SKB data starting with MAC header to cfgState->buf. We will pull
1695 * entire skb->len from skb and then we will push cfgState->buf to skb
1696 * */
1697 if( NULL == skb_pull(skb, skb->len) )
1698 {
1699 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
1700 kfree_skb(cfgState->skb);
1701 return;
1702 }
1703
1704 data = skb_push( skb, cfgState->len );
1705
1706 if (data == NULL)
1707 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08001708 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001709 kfree_skb( cfgState->skb );
1710 return;
1711 }
1712
1713 memcpy( data, cfgState->buf, cfgState->len );
1714
1715 /* send frame to monitor interfaces now */
1716 if( skb_headroom(skb) < rtHdrLen )
1717 {
1718 hddLog( LOGE, FL("No headroom for rtap header"));
1719 kfree_skb(cfgState->skb);
1720 return;
1721 }
1722
1723 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
1724
1725 memset( rthdr, 0, rtHdrLen );
1726 rthdr->it_len = cpu_to_le16( rtHdrLen );
1727 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
1728 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
1729 );
1730
1731 pos = (unsigned char *)( rthdr+1 );
1732
1733 // Fill TX flags
1734 *pos = actionSendSuccess;
1735 pos += 2;
1736
1737 // Fill retry count
1738 *pos = 0;
1739 pos++;
1740
1741 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001742 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001743 skb->pkt_type = PACKET_OTHERHOST;
1744 skb->protocol = htons(ETH_P_802_2);
1745 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001746#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001747#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001748 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001749#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001750#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001751 if (in_interrupt())
1752 netif_rx( skb );
1753 else
1754 netif_rx_ni( skb );
1755
1756 /* Enable Queues which we have disabled earlier */
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05301757 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07001758
1759}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05301760