blob: 6e74b2a2bd89ad8839e9ce8c4707eb4bdf0bf7ee [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 ========================================================================*/
53#ifdef CONFIG_CFG80211
54
55#include <wlan_hdd_includes.h>
56#include <wlan_hdd_hostapd.h>
57#include <net/cfg80211.h>
58#include "sme_Api.h"
59#include "wlan_hdd_p2p.h"
60#include "sapApi.h"
61
62#include <linux/netdevice.h>
63#include <linux/skbuff.h>
64#include <linux/etherdevice.h>
65#include <net/ieee80211_radiotap.h>
66
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080067//Ms to Micro Sec
68#define MS_TO_MUS(x) ((x)*1000);
69
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070070#ifdef WLAN_FEATURE_P2P_DEBUG
71#define MAX_P2P_ACTION_FRAME_TYPE 9
72const char *p2p_action_frame_type[]={"GO Negotiation Request",
73 "GO Negotiation Response",
74 "GO Negotiation Confirmation",
75 "P2P Invitation Request",
76 "P2P Invitation Response",
77 "Device Discoverability Request",
78 "Device Discoverability Response",
79 "Provision Discovery Request",
80 "Provision Discovery Response"};
81
82/* We no need to protect this variable since
83 * there is no chance of race to condition
84 * and also not make any complicating the code
85 * just for debugging log
86 */
87tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
88
89#endif
90
Jeff Johnson295189b2012-06-20 16:38:30 -070091extern struct net_device_ops net_ops_struct;
92
93static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
94 int rtap_len, int flag );
95
96static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
97 hdd_cfg80211_state_t* cfgState,
98 tANI_BOOLEAN actionSendSuccess );
99
100static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
101 tANI_U32 nFrameLength,
102 tANI_U8* pbFrames,
103 tANI_U8 frameType );
104
105#ifdef WLAN_FEATURE_P2P
106eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
107 eHalStatus status )
108{
109 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700110 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
111 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
112
113 if( pRemainChanCtx == NULL )
114 {
115 hddLog( LOGW,
116 "%s: No Rem on channel pending for which Rsp is received", __func__);
117 return eHAL_STATUS_SUCCESS;
118 }
119
120 hddLog( LOG1, "Received remain on channel rsp");
121
122 cfgState->remain_on_chan_ctx = NULL;
123
124 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
125 {
126 if( cfgState->buf )
127 {
128 hddLog( LOGP,
129 "%s: We need to receive yet an ack from one of tx packet",
130 __func__);
131 }
132 cfg80211_remain_on_channel_expired( pRemainChanCtx->dev,
133 pRemainChanCtx->cookie,
134 &pRemainChanCtx->chan,
135 pRemainChanCtx->chan_type, GFP_KERNEL );
136 }
137
Jeff Johnson295189b2012-06-20 16:38:30 -0700138
139 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700140 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
141 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700142 )
143 {
144 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800145 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
146 {
147 sme_DeregisterMgmtFrame(
148 hHal, sessionId,
149 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
150 NULL, 0 );
151 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700152 }
153 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
154 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
155 )
156 {
157 WLANSAP_DeRegisterMgmtFrame(
158 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
159 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
160 NULL, 0 );
161 }
162
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800163 vos_mem_free( pRemainChanCtx );
Jeff Johnson295189b2012-06-20 16:38:30 -0700164 complete(&pAdapter->cancel_rem_on_chan_var);
165 return eHAL_STATUS_SUCCESS;
166}
167
Jeff Johnson32d95a32012-09-10 13:15:23 -0700168static void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700169{
Jeff Johnson295189b2012-06-20 16:38:30 -0700170 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
171 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700172
Jeff Johnson32d95a32012-09-10 13:15:23 -0700173 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700174 {
Jeff Johnson32d95a32012-09-10 13:15:23 -0700175 hddLog( LOG1, "Cancel Existing Remain on Channel");
176
177 /* Wait till remain on channel ready indication before issuing cancel
178 * remain on channel request, otherwise if remain on channel not
179 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700180 * will be in unknown state.
181 */
182 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
183 msecs_to_jiffies(WAIT_REM_CHAN_READY));
184 if (!status)
185 {
186 hddLog( LOGE,
187 "%s: timeout waiting for remain on channel ready indication",
188 __func__);
189 }
190
191 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700192
Jeff Johnson295189b2012-06-20 16:38:30 -0700193 /* Issue abort remain on chan request to sme.
194 * The remain on channel callback will make sure the remain_on_chan
195 * expired event is sent.
196 */
197 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700198 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
199 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700200 )
201 {
202 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
203 pAdapter->sessionId );
204 }
205 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
206 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
207 )
208 {
209 WLANSAP_CancelRemainOnChannel(
210 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
211 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700212
Jeff Johnson32d95a32012-09-10 13:15:23 -0700213 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700214 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700215
216 if (!status)
217 {
218 hddLog( LOGE,
219 "%s: timeout waiting for cancel remain on channel ready indication",
220 __func__);
221 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700222 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700223}
224
225int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
226{
227 int status = 0;
228 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
229
230 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
231 {
232 //Cancel Existing Remain On Channel
233 //If no action frame is pending
234 if( cfgState->remain_on_chan_ctx != NULL)
235 {
236 //Check whether Action Frame is pending or not
237 if( cfgState->buf == NULL)
238 {
239 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
240 }
241 else
242 {
243 hddLog( LOG1, "Cannot Cancel Existing Remain on Channel");
244 status = -EBUSY;
245 }
246 }
247 }
248 return status;
249}
250
251static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
252 struct net_device *dev,
253 struct ieee80211_channel *chan,
254 enum nl80211_channel_type channel_type,
255 unsigned int duration, u64 *cookie,
256 rem_on_channel_request_type_t request_type )
257{
258 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
259 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
260 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
261 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
262 __func__,pAdapter->device_mode);
263
264 hddLog( LOG1,
265 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d",
266 chan->hw_value, chan->center_freq, channel_type, duration );
267
268 //Cancel existing remain On Channel if any
269 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270
Jeff Johnsone7245742012-09-05 17:12:55 -0700271 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700273 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 * channel requets when Load/Unload is in progress*/
275 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
276 {
277 hddLog( LOGE,
278 "%s: Wlan Load/Unload is in progress", __func__);
279 return -EBUSY;
280 }
281
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700282 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
283 {
284 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
285 "%s:LOGP in Progress. Ignore!!!", __func__);
286 return -EAGAIN;
287 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700288 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
289 if( NULL == pRemainChanCtx )
290 {
291 hddLog(VOS_TRACE_LEVEL_FATAL,
292 "%s: Not able to allocate memory for Channel context",
293 __func__);
294 return -ENOMEM;
295 }
296
297 vos_mem_copy( &pRemainChanCtx->chan, chan,
298 sizeof(struct ieee80211_channel) );
299
300 pRemainChanCtx->chan_type = channel_type;
301 pRemainChanCtx->duration = duration;
302 pRemainChanCtx->dev = dev;
303 *cookie = (tANI_U32) pRemainChanCtx;
304 pRemainChanCtx->cookie = *cookie;
305 pRemainChanCtx->rem_on_chan_request = request_type;
306 cfgState->remain_on_chan_ctx = pRemainChanCtx;
307 cfgState->current_freq = chan->center_freq;
308
309 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
310
311 //call sme API to start remain on channel.
312 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700313 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
314 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700315 )
316 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700317 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700318 //call sme API to start remain on channel.
319 sme_RemainOnChannel(
320 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
321 chan->hw_value, duration,
322 wlan_hdd_remain_on_channel_callback, pAdapter );
323
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800324 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
325 {
326 sme_RegisterMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
327 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
328 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 );
329 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700330
331 }
332 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
333 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
334 )
335 {
336 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700337 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700338 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
339 chan->hw_value, duration,
340 wlan_hdd_remain_on_channel_callback, pAdapter ))
341
342 {
343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
344 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
345 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700346 vos_mem_free (pRemainChanCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700347 return -EINVAL;
348 }
349
350
Jeff Johnson43971f52012-07-17 12:26:56 -0700351 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700352 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
353 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
354 NULL, 0 ))
355 {
356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
357 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
358 WLANSAP_CancelRemainOnChannel(
359 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
360 return -EINVAL;
361 }
362
363 }
364 return 0;
365
366}
367
368int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
369 struct net_device *dev,
370 struct ieee80211_channel *chan,
371 enum nl80211_channel_type channel_type,
372 unsigned int duration, u64 *cookie )
373{
374 return wlan_hdd_request_remain_on_channel(wiphy, dev,
375 chan, channel_type, duration, cookie,
376 REMAIN_ON_CHANNEL_REQUEST);
377}
378
379void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
380{
381 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
382 hdd_remain_on_chan_ctx_t* pRemainChanCtx = cfgState->remain_on_chan_ctx;
383
384 hddLog( LOG1, "Ready on chan ind");
385
386 if( pRemainChanCtx != NULL )
387 {
388 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
389 {
390 cfg80211_ready_on_channel( pAdapter->dev, (tANI_U32)pRemainChanCtx,
391 &pRemainChanCtx->chan, pRemainChanCtx->chan_type,
392 pRemainChanCtx->duration, GFP_KERNEL );
393 }
394#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
395 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request )
396 {
397 complete(&pAdapter->offchannel_tx_event);
398 }
399#endif
400 complete(&pAdapter->rem_on_chan_ready_event);
401 }
402 else
403 {
404 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
405 }
406 return;
407}
408
409int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
410 struct net_device *dev, u64 cookie )
411{
412 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700413 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
414 int status = 0;
415
416 hddLog( LOG1, "Cancel remain on channel req");
417
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700418 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
419 {
420 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
421 "%s:LOGP in Progress. Ignore!!!", __func__);
422 return -EAGAIN;
423 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700424 /* FIXME cancel currently running remain on chan.
425 * Need to check cookie and cancel accordingly
426 */
427 if( (cfgState->remain_on_chan_ctx == NULL) ||
428 (cfgState->remain_on_chan_ctx->cookie != cookie) )
429 {
430 hddLog( LOGE,
431 "%s: No Remain on channel pending with specified cookie value",
432 __func__);
433 return -EINVAL;
434 }
435
436 /* wait until remain on channel ready event received
437 * for already issued remain on channel request */
438 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
439 msecs_to_jiffies(WAIT_REM_CHAN_READY));
440 if (!status)
441 {
442 hddLog( LOGE,
443 "%s: timeout waiting for remain on channel ready indication",
444 __func__);
445 }
446 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
447 /* Issue abort remain on chan request to sme.
448 * The remain on channel callback will make sure the remain_on_chan
449 * expired event is sent.
450 */
451 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700452 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
453 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700454 )
455 {
456 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700457 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
458 sessionId );
459 }
460 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
461 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
462 )
463 {
464 WLANSAP_CancelRemainOnChannel(
465 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
466 }
467 else
468 {
469 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
470 __func__, pAdapter->device_mode);
471 return -EIO;
472 }
473 wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
474 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
475 return 0;
476}
477
478#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
479int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
480 struct ieee80211_channel *chan, bool offchan,
481 enum nl80211_channel_type channel_type,
482 bool channel_type_valid, unsigned int wait,
483 const u8 *buf, size_t len, bool no_cck,
484 bool dont_wait_for_ack, u64 *cookie )
485#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
486int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
487 struct ieee80211_channel *chan, bool offchan,
488 enum nl80211_channel_type channel_type,
489 bool channel_type_valid, unsigned int wait,
490 const u8 *buf, size_t len, u64 *cookie )
491#else
492int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
493 struct ieee80211_channel *chan,
494 enum nl80211_channel_type channel_type,
495 bool channel_type_valid,
496 const u8 *buf, size_t len, u64 *cookie )
497#endif //LINUX_VERSION_CODE
498{
499 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
500 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700501 tANI_U16 extendedWait = 0;
502 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
503 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
504 tActionFrmType actionFrmType;
505 bool noack = 0;
506
Jeff Johnson295189b2012-06-20 16:38:30 -0700507#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
508 hdd_adapter_t *goAdapter;
509#endif
510
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700511#ifdef WLAN_FEATURE_P2P_DEBUG
512 if ((type == SIR_MAC_MGMT_FRAME) &&
513 (subType == SIR_MAC_MGMT_ACTION) &&
514 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
515 {
516 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
517 if(actionFrmType > MAX_P2P_ACTION_FRAME_TYPE)
518 {
519 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
520 actionFrmType);
521 }
522 else
523 {
524 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
525 p2p_action_frame_type[actionFrmType]);
526 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
527 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
528 {
529 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
530 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800531 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700532 }
533 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
534 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
535 {
536 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
537 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
538 " completed state");
539 }
540 }
541 }
542#endif
543
Jeff Johnsone7245742012-09-05 17:12:55 -0700544#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
545 noack = dont_wait_for_ack;
546#endif
547
548 //If the wait is coming as 0 with off channel set
549 //then set the wait to 200 ms
550 if (offchan && !wait)
551 wait = ACTION_FRAME_DEFAULT_WAIT;
552
Jeff Johnson295189b2012-06-20 16:38:30 -0700553 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
554 __func__,pAdapter->device_mode);
555
556 //Call sme API to send out a action frame.
557 // OR can we send it directly through data path??
558 // After tx completion send tx status back.
559 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
560 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
561 )
562 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700563 if (type == SIR_MAC_MGMT_FRAME)
564 {
565 if (subType == SIR_MAC_MGMT_PROBE_RSP)
566 {
567 /* Drop Probe response recieved from supplicant, as for GO and
568 SAP PE itself sends probe response
569 */
570 goto err_rem_channel;
571 }
572 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
573 (subType == SIR_MAC_MGMT_DEAUTH))
574 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700575 /* During EAP failure or P2P Group Remove supplicant
576 * is sending del_station command to driver. From
577 * del_station function, Driver will send deauth frame to
578 * p2p client. No need to send disassoc frame from here.
579 * so Drop the frame here and send tx indication back to
580 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700581 */
582 tANI_U8 dstMac[ETH_ALEN] = {0};
583 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700584 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700585 "%s: Deauth/Disassoc received for STA:"
Jeff Johnsone7245742012-09-05 17:12:55 -0700586 "%02x:%02x:%02x:%02x:%02x:%02x",
587 __func__,
588 dstMac[0], dstMac[1], dstMac[2],
Jeff Johnson295189b2012-06-20 16:38:30 -0700589 dstMac[3], dstMac[4], dstMac[5]);
Jeff Johnson295189b2012-06-20 16:38:30 -0700590 goto err_rem_channel;
591 }
592 }
593 }
594
595 if( NULL != cfgState->buf )
596 return -EBUSY;
597
598 hddLog( LOG1, "Action frame tx request");
599
600#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
601 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
602
603 //If GO adapter exists and operating on same frequency
604 //then we will not request remain on channel
605 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
606 == goAdapter->sessionCtx.ap.operatingChannel ) )
607 {
608 goto send_frame;
609 }
610#endif
611
612#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
613 if( offchan && wait)
614 {
615 int status;
616
617 // In case of P2P Client mode if we are already
618 // on the same channel then send the frame directly
619
620 if((cfgState->remain_on_chan_ctx != NULL) &&
621 (cfgState->current_freq == chan->center_freq)
622 )
623 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700624 hddLog(LOG1,"action frame: extending the wait time\n");
625 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 goto send_frame;
627 }
628
629 INIT_COMPLETION(pAdapter->offchannel_tx_event);
630
631 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
632 chan, channel_type, wait, cookie,
633 OFF_CHANNEL_ACTION_TX);
634
635 if(0 != status)
636 {
637 if( (-EBUSY == status) &&
638 (cfgState->current_freq == chan->center_freq) )
639 {
640 goto send_frame;
641 }
642 goto err_rem_channel;
643 }
644
645 /* Wait for driver to be ready on the requested channel */
646 status = wait_for_completion_interruptible_timeout(
647 &pAdapter->offchannel_tx_event,
648 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
649 if(!status)
650 {
651 hddLog( LOGE, "Not able to complete remain on channel request"
652 " within timeout period");
653 goto err_rem_channel;
654 }
655 }
656 else if ( offchan )
657 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700658 /* Check before sending action frame
659 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -0700660 if(NULL == cfgState->remain_on_chan_ctx)
661 {
662 goto err_rem_channel;
663 }
664 }
665 send_frame:
666#endif
667
Jeff Johnsone7245742012-09-05 17:12:55 -0700668 if(!noack)
669 {
670 cfgState->buf = vos_mem_malloc( len ); //buf;
671 if( cfgState->buf == NULL )
672 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -0700673
Jeff Johnsone7245742012-09-05 17:12:55 -0700674 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -0700675
Jeff Johnsone7245742012-09-05 17:12:55 -0700676 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700677
678#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700679 if( cfgState->remain_on_chan_ctx )
680 {
681 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
682 *cookie = cfgState->action_cookie;
683 }
684 else
685 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700686#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700687 *cookie = (tANI_U32) cfgState->buf;
688 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -0700689#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700690 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700691#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700692 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700693
694 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700695 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
696 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700697 )
698 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700699 tANI_U8 sessionId = pAdapter->sessionId;
700 if ((type == SIR_MAC_MGMT_FRAME) &&
701 (subType == SIR_MAC_MGMT_ACTION) &&
702 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -0700703 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700704 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
705 hddLog(LOG1, "Tx Action Frame %u \n", actionFrmType);
706 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -0700707 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700708 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
709 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING \n", __func__);
710 }
711 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
712 {
713 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
714 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700715 }
716 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700717
Jeff Johnson295189b2012-06-20 16:38:30 -0700718 if (eHAL_STATUS_SUCCESS !=
719 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -0700720 sessionId, buf, len, extendedWait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -0700721 {
722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
723 "%s: sme_sendAction returned fail", __func__);
724 goto err;
725 }
726 }
727 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
728 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
729 )
730 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700731 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700732 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700733 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700734 {
735 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
736 "%s: WLANSAP_SendAction returned fail", __func__);
737 goto err;
738 }
739 }
740
741 return 0;
742err:
Jeff Johnsone7245742012-09-05 17:12:55 -0700743 if(!noack)
744 {
745 hdd_sendActionCnf( pAdapter, FALSE );
746 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700747 return 0;
748err_rem_channel:
749 *cookie = (tANI_U32)cfgState;
750 cfg80211_mgmt_tx_status( pAdapter->dev, *cookie, buf, len, FALSE, GFP_KERNEL );
751 return 0;
752}
753
754#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
755int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
756 struct net_device *dev,
757 u64 cookie)
758{
759 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
760}
761#endif
762
763void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
764{
765 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
766
Jeff Johnsone7245742012-09-05 17:12:55 -0700767 cfgState->actionFrmState = HDD_IDLE;
768
Jeff Johnson295189b2012-06-20 16:38:30 -0700769 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
770 if( NULL == cfgState->buf )
771 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700772 return;
773 }
774
775 /* If skb is NULL it means this packet was received on CFG80211 interface
776 * else it was received on Monitor interface */
777 if( cfgState->skb == NULL )
778 {
779 /*
780 * buf is the same pointer it passed us to send. Since we are sending
781 * it through control path, we use different buffers.
782 * In case of mac80211, they just push it to the skb and pass the same
783 * data while sending tx ack status.
784 * */
785 cfg80211_mgmt_tx_status( pAdapter->dev, cfgState->action_cookie,
786 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
787 vos_mem_free( cfgState->buf );
788 cfgState->buf = NULL;
789 }
790 else
791 {
792 hdd_adapter_t* pMonAdapter =
793 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
794 if( pMonAdapter == NULL )
795 {
796 hddLog( LOGE, "Not able to get Monitor Adapter");
797 cfgState->skb = NULL;
798 vos_mem_free( cfgState->buf );
799 cfgState->buf = NULL;
800 complete(&pAdapter->tx_action_cnf_event);
801 return;
802 }
803 /* Send TX completion feedback over monitor interface. */
804 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
805 cfgState->skb = NULL;
806 vos_mem_free( cfgState->buf );
807 cfgState->buf = NULL;
808 /* Look for the next Mgmt packet to TX */
809 hdd_mon_tx_mgmt_pkt(pAdapter);
810 }
811 complete(&pAdapter->tx_action_cnf_event);
812}
813
814/**
815 * hdd_setP2pNoa
816 *
817 *FUNCTION:
818 * This function is called from hdd_hostapd_ioctl function when Driver
819 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
820 *
821 *LOGIC:
822 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
823 *
824 *ASSUMPTIONS:
825 *
826 *
827 *NOTE:
828 *
829 * @param dev Pointer to net device structure
830 * @param command Pointer to command
831 *
832 * @return Status
833 */
834
835int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
836{
837 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
838 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
839 VOS_STATUS status = VOS_STATUS_SUCCESS;
840 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800841 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -0700842 char *param;
843
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -0800844 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -0700845 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800846 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700847 param++;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800848 sscanf(param, "%d %d %d", &count, &start_time, &duration);
Jeff Johnson295189b2012-06-20 16:38:30 -0700849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
850 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d \n",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800851 __func__, count, start_time, duration);
852 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -0700853 /* PS Selection
854 * Periodic NoA (2)
855 * Single NOA (4)
856 */
857 NoA.opp_ps = 0;
858 NoA.ctWindow = 0;
859 if (count == 1)
860 {
861 NoA.duration = 0;
862 NoA.single_noa_duration = duration;
863 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
864 }
865 else
866 {
867 NoA.duration = duration;
868 NoA.single_noa_duration = 0;
869 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
870 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800871 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -0700872 NoA.count = count;
873 NoA.sessionid = pAdapter->sessionId;
874
875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
876 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
877 "interval %d count %d single noa duration %d "
878 "PsSelection %x \n", __func__, NoA.opp_ps,
879 NoA.ctWindow, NoA.duration, NoA.interval,
880 NoA.count, NoA.single_noa_duration,
881 NoA.psSelection);
882
883 sme_p2pSetPs(hHal, &NoA);
884 return status;
885}
886
887/**
888 * hdd_setP2pOpps
889 *
890 *FUNCTION:
891 * This function is called from hdd_hostapd_ioctl function when Driver
892 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
893 *
894 *LOGIC:
895 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
896 *
897 *ASSUMPTIONS:
898 *
899 *
900 *NOTE:
901 *
902 * @param dev Pointer to net device structure
903 * @param command Pointer to command
904 *
905 * @return Status
906 */
907
908int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
909{
910 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
911 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
912 VOS_STATUS status = VOS_STATUS_SUCCESS;
913 tP2pPsConfig NoA;
914 char *param;
915 int legacy_ps, opp_ps, ctwindow;
916
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -0800917 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -0700918 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800919 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700920 param++;
921 sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
922 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
923 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d \n",
924 __func__, legacy_ps, opp_ps, ctwindow);
925
926 /* PS Selection
927 * Opportunistic Power Save (1)
928 */
929
930 /* From wpa_cli user need to use separate command to set ctWindow and Opps
931 * When user want to set ctWindow during that time other parameters
932 * values are coming from wpa_supplicant as -1.
933 * Example : User want to set ctWindow with 30 then wpa_cli command :
934 * P2P_SET ctwindow 30
935 * Command Received at hdd_hostapd_ioctl is as below:
936 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
937 */
938 if (ctwindow != -1)
939 {
940
941 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
942 "Opportunistic Power Save is %s \n",
943 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
944
945 if (ctwindow != pAdapter->ctw)
946 {
947 pAdapter->ctw = ctwindow;
948
949 if(pAdapter->ops)
950 {
951 NoA.opp_ps = pAdapter->ops;
952 NoA.ctWindow = pAdapter->ctw;
953 NoA.duration = 0;
954 NoA.single_noa_duration = 0;
955 NoA.interval = 0;
956 NoA.count = 0;
957 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
958 NoA.sessionid = pAdapter->sessionId;
959
960 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
961 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
962 "interval %d count %d single noa duration %d "
963 "PsSelection %x \n", __func__, NoA.opp_ps,
964 NoA.ctWindow, NoA.duration, NoA.interval,
965 NoA.count, NoA.single_noa_duration,
966 NoA.psSelection);
967
968 sme_p2pSetPs(hHal, &NoA);
969 }
970 return 0;
971 }
972 }
973
974 if (opp_ps != -1)
975 {
976 pAdapter->ops = opp_ps;
977
978 if ((opp_ps != -1) && (pAdapter->ctw))
979 {
980 NoA.opp_ps = opp_ps;
981 NoA.ctWindow = pAdapter->ctw;
982 NoA.duration = 0;
983 NoA.single_noa_duration = 0;
984 NoA.interval = 0;
985 NoA.count = 0;
986 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
987 NoA.sessionid = pAdapter->sessionId;
988
989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
990 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
991 "interval %d count %d single noa duration %d "
992 "PsSelection %x \n", __func__, NoA.opp_ps,
993 NoA.ctWindow, NoA.duration, NoA.interval,
994 NoA.count, NoA.single_noa_duration,
995 NoA.psSelection);
996
997 sme_p2pSetPs(hHal, &NoA);
998 }
999 }
1000 return status;
1001}
1002
1003int hdd_setP2pPs( struct net_device *dev, void *msgData )
1004{
1005 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1006 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1007 VOS_STATUS status = VOS_STATUS_SUCCESS;
1008 tP2pPsConfig NoA;
1009 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1010
1011 NoA.opp_ps = pappNoA->opp_ps;
1012 NoA.ctWindow = pappNoA->ctWindow;
1013 NoA.duration = pappNoA->duration;
1014 NoA.interval = pappNoA->interval;
1015 NoA.count = pappNoA->count;
1016 NoA.single_noa_duration = pappNoA->single_noa_duration;
1017 NoA.psSelection = pappNoA->psSelection;
1018 NoA.sessionid = pAdapter->sessionId;
1019
1020 sme_p2pSetPs(hHal, &NoA);
1021 return status;
1022}
1023#endif
1024
1025static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1026{
1027 tANI_U8 sessionType;
1028
1029 switch( type )
1030 {
1031 case NL80211_IFTYPE_AP:
1032 sessionType = WLAN_HDD_SOFTAP;
1033 break;
1034 case NL80211_IFTYPE_P2P_GO:
1035 sessionType = WLAN_HDD_P2P_GO;
1036 break;
1037 case NL80211_IFTYPE_P2P_CLIENT:
1038 sessionType = WLAN_HDD_P2P_CLIENT;
1039 break;
1040 case NL80211_IFTYPE_STATION:
1041 sessionType = WLAN_HDD_INFRA_STATION;
1042 break;
1043 case NL80211_IFTYPE_MONITOR:
1044 sessionType = WLAN_HDD_MONITOR;
1045 break;
1046 default:
1047 sessionType = WLAN_HDD_INFRA_STATION;
1048 break;
1049 }
1050
1051 return sessionType;
1052}
1053
1054#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1055struct net_device* wlan_hdd_add_virtual_intf(
1056 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1057 u32 *flags, struct vif_params *params )
1058#else
1059int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1060 enum nl80211_iftype type,
1061 u32 *flags, struct vif_params *params )
1062#endif
1063{
1064 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1065 hdd_adapter_t* pAdapter = NULL;
1066
1067 ENTER();
1068
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001069 if(hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
1070 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001071 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001072 "interfaces of same type are not supported currently.",__func__, type);
Jeff Johnsond13512a2012-07-17 11:42:19 -07001073 return NULL;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001074 }
1075
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001076 if (pHddCtx->isLogpInProgress)
1077 {
1078 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1079 "%s:LOGP in Progress. Ignore!!!", __func__);
1080#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1081 return NULL;
1082#else
1083 return -EAGAIN;
1084#endif
1085 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001086 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
1087 {
1088 if( (NL80211_IFTYPE_P2P_GO == type) ||
1089 (NL80211_IFTYPE_P2P_CLIENT == type) )
1090 {
1091 /* Generate the P2P Interface Address. this address must be
1092 * different from the P2P Device Address.
1093 */
1094 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1095 p2pDeviceAddress.bytes[4] ^= 0x80;
1096 pAdapter = hdd_open_adapter( pHddCtx,
1097 wlan_hdd_get_session_type(type),
1098 name, p2pDeviceAddress.bytes,
1099 VOS_TRUE );
1100 }
1101 }
1102 else
1103 {
1104 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1105 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1106 }
1107
1108 if( NULL == pAdapter)
1109 {
1110 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1111#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1112 return NULL;
1113#else
1114 return -EINVAL;
1115#endif
1116 }
1117 EXIT();
1118#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1119 return pAdapter->dev;
1120#else
1121 return 0;
1122#endif
1123}
1124
1125int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
1126{
1127 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1128 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1129 ENTER();
1130
1131 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1132 __func__,pVirtAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001133 if (pHddCtx->isLogpInProgress)
1134 {
1135 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1136 "%s:LOGP in Progress. Ignore!!!", __func__);
1137 return -EAGAIN;
1138 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001139
1140 wlan_hdd_release_intf_addr( pHddCtx,
1141 pVirtAdapter->macAddressCurrent.bytes );
1142
1143 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1144 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1145 EXIT();
1146 return 0;
1147}
1148
1149void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
1150 tANI_U32 nFrameLength, tANI_U8* pbFrames,
1151 tANI_U8 frameType )
1152{
1153 //Indicate a Frame over Monitor Intf.
1154 int rxstat;
1155 struct sk_buff *skb = NULL;
1156 int needed_headroom = 0;
1157 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1158 HDD_RX_FLAG_MMIC_STRIPPED;
Jeff Johnsone7245742012-09-05 17:12:55 -07001159#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1160 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001162 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1163
1164 VOS_ASSERT( (pbFrames != NULL) );
1165
1166 /* room for the radiotap header based on driver features
1167 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1168 * RX flags.
1169 * */
1170 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1171
1172 //alloc skb here
1173 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1174 if (unlikely(NULL == skb))
1175 {
1176 hddLog( LOGW, FL("Unable to allocate skb"));
1177 return;
1178 }
1179 skb_reserve(skb, VPKT_SIZE_BUFFER);
1180 if (unlikely(skb_headroom(skb) < nFrameLength))
1181 {
1182 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1183 "HDD [%d]: Insufficient headroom, "
1184 "head[%p], data[%p], req[%d]",
1185 __LINE__, skb->head, skb->data, nFrameLength);
1186 kfree_skb(skb);
1187 return ;
1188 }
1189 // actually push the data
1190 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1191 /* prepend radiotap information */
1192 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1193 {
1194 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1195 //free skb
1196 kfree_skb(skb);
1197 return ;
1198 }
1199
1200 skb_reset_mac_header( skb );
1201 skb->dev = pMonAdapter->dev;
1202 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001203 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnsone7245742012-09-05 17:12:55 -07001204#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1205 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1206#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001207 rxstat = netif_rx_ni(skb);
1208 if( NET_RX_SUCCESS == rxstat )
1209 {
1210 hddLog( LOG1, FL("Success"));
1211 }
1212 else
1213 hddLog( LOGE, FL("Failed %d"), rxstat);
1214
1215 return ;
1216}
1217
1218void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
1219 tANI_U32 nFrameLength,
1220 tANI_U8* pbFrames,
1221 tANI_U8 frameType,
1222 tANI_U32 rxChan )
1223{
1224 tANI_U16 freq;
Jeff Johnsone7245742012-09-05 17:12:55 -07001225 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001226 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001227 tActionFrmType actionFrmType;
1228 hdd_cfg80211_state_t *cfgState = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001229
1230 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d\n",
1231 __func__, frameType, nFrameLength);
1232
1233 if (NULL == pAdapter)
1234 {
1235 hddLog( LOGE, FL("pAdapter is NULL"));
1236 return;
1237 }
1238
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001239 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1240 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1241
1242 /* Get pAdapter from Destination mac address of the frame */
1243 if ((type == SIR_MAC_MGMT_FRAME) &&
1244 (subType != SIR_MAC_MGMT_PROBE_REQ))
1245 {
1246 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1247 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1248 if (NULL == pAdapter)
1249 {
1250 /* Under assumtion that we don't receive any action frame
1251 * with BCST as destination we dropping action frame
1252 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001253 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1254 MAC_ADDRESS_STR ,
1255 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1256 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
1257 " subType = %d \n",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001258 return;
1259 }
1260 }
1261
Jeff Johnson295189b2012-06-20 16:38:30 -07001262 if (NULL == pAdapter->dev)
1263 {
1264 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1265 return;
1266 }
1267
1268 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1269 {
1270 hddLog( LOGE, FL("pAdapter has invalid magic"));
1271 return;
1272 }
1273
1274 if( !nFrameLength )
1275 {
1276 hddLog( LOGE, FL("Frame Length is Invalid ZERO"));
1277 return;
1278 }
1279
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07001280 if (NULL == pbFrames) {
1281 hddLog( LOGE, FL("pbFrames is NULL"));
1282 return;
1283 }
1284
1285
Jeff Johnson295189b2012-06-20 16:38:30 -07001286 if( ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
1287 || ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1288 )
1289 {
1290 hdd_adapter_t *pMonAdapter =
1291 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1292
1293 if( NULL != pMonAdapter )
1294 {
1295 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1296 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1297 pbFrames, frameType);
1298 return;
1299 }
1300 }
1301
1302 //Channel indicated may be wrong. TODO
1303 //Indicate an action frame.
1304 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1305 {
1306 freq = ieee80211_channel_to_frequency( rxChan,
1307 IEEE80211_BAND_2GHZ);
1308 }
1309 else
1310 {
1311 freq = ieee80211_channel_to_frequency( rxChan,
1312 IEEE80211_BAND_5GHZ);
1313 }
1314
Jeff Johnsone7245742012-09-05 17:12:55 -07001315 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1316
1317 if ((type == SIR_MAC_MGMT_FRAME) &&
1318 (subType == SIR_MAC_MGMT_ACTION) &&
1319 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
1320 {
1321 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Jeff Johnson1250df42012-12-10 14:31:52 -08001322 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001323#ifdef WLAN_FEATURE_P2P_DEBUG
1324 if(actionFrmType > MAX_P2P_ACTION_FRAME_TYPE)
1325 {
1326 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1327 actionFrmType);
1328 }
1329 else
1330 {
1331 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1332 p2p_action_frame_type[actionFrmType]);
1333 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1334 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1335 {
1336 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1337 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001338 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001339 }
1340 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1341 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1342 {
1343 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001344 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1345 "GO negotiation completed state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001346 }
1347 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1348 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1349 {
1350 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001351 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1352 " completed state Autonomous GO formation");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001353 }
1354 }
1355#endif
1356
Jeff Johnsone7245742012-09-05 17:12:55 -07001357 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
1358 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
1359 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
1360 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
1361 {
1362 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
1363 __func__);
1364 hdd_sendActionCnf(pAdapter, TRUE);
1365 }
1366 }
1367
Jeff Johnson295189b2012-06-20 16:38:30 -07001368 //Indicate Frame Over Normal Interface
1369 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
1370
1371#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
1372 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
1373 pbFrames, nFrameLength,
1374 GFP_ATOMIC );
1375#else
1376 cfg80211_rx_mgmt( pAdapter->dev, freq,
1377 pbFrames, nFrameLength,
1378 GFP_ATOMIC );
1379#endif //LINUX_VERSION_CODE
1380}
1381
1382/*
1383 * ieee80211_add_rx_radiotap_header - add radiotap header
1384 */
1385static int hdd_wlan_add_rx_radiotap_hdr (
1386 struct sk_buff *skb, int rtap_len, int flag )
1387{
1388 u8 rtap_temp[20] = {0};
1389 struct ieee80211_radiotap_header *rthdr;
1390 unsigned char *pos;
1391 u16 rx_flags = 0;
1392
1393 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
1394
1395 /* radiotap header, set always present flags */
1396 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
1397 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
1398 rthdr->it_len = cpu_to_le16(rtap_len);
1399
1400 pos = (unsigned char *) (rthdr + 1);
1401
1402 /* the order of the following fields is important */
1403
1404 /* IEEE80211_RADIOTAP_FLAGS */
1405 *pos = 0;
1406 pos++;
1407
1408 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
1409 /* ensure 2 byte alignment for the 2 byte field as required */
1410 if ((pos - (u8 *)rthdr) & 1)
1411 pos++;
1412 put_unaligned_le16(rx_flags, pos);
1413 pos += 2;
1414
1415 // actually push the data
1416 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
1417
1418 return 0;
1419}
1420
1421static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
1422 hdd_cfg80211_state_t* cfgState,
1423 tANI_BOOLEAN actionSendSuccess )
1424{
1425 struct ieee80211_radiotap_header *rthdr;
1426 unsigned char *pos;
1427 struct sk_buff *skb = cfgState->skb;
Jeff Johnsone7245742012-09-05 17:12:55 -07001428#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1429 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
1430#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001431
1432 /* 2 Byte for TX flags and 1 Byte for Retry count */
1433 u32 rtHdrLen = sizeof(*rthdr) + 3;
1434
1435 u8 *data;
1436
1437 /* We have to return skb with Data starting with MAC header. We have
1438 * copied SKB data starting with MAC header to cfgState->buf. We will pull
1439 * entire skb->len from skb and then we will push cfgState->buf to skb
1440 * */
1441 if( NULL == skb_pull(skb, skb->len) )
1442 {
1443 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
1444 kfree_skb(cfgState->skb);
1445 return;
1446 }
1447
1448 data = skb_push( skb, cfgState->len );
1449
1450 if (data == NULL)
1451 {
1452 hddLog( LOGE, FL("Not Able to Push %d byte to skb"), cfgState->len);
1453 kfree_skb( cfgState->skb );
1454 return;
1455 }
1456
1457 memcpy( data, cfgState->buf, cfgState->len );
1458
1459 /* send frame to monitor interfaces now */
1460 if( skb_headroom(skb) < rtHdrLen )
1461 {
1462 hddLog( LOGE, FL("No headroom for rtap header"));
1463 kfree_skb(cfgState->skb);
1464 return;
1465 }
1466
1467 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
1468
1469 memset( rthdr, 0, rtHdrLen );
1470 rthdr->it_len = cpu_to_le16( rtHdrLen );
1471 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
1472 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
1473 );
1474
1475 pos = (unsigned char *)( rthdr+1 );
1476
1477 // Fill TX flags
1478 *pos = actionSendSuccess;
1479 pos += 2;
1480
1481 // Fill retry count
1482 *pos = 0;
1483 pos++;
1484
1485 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001486 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001487 skb->pkt_type = PACKET_OTHERHOST;
1488 skb->protocol = htons(ETH_P_802_2);
1489 memset( skb->cb, 0, sizeof( skb->cb ) );
Jeff Johnsone7245742012-09-05 17:12:55 -07001490#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1491 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1492#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001493 if (in_interrupt())
1494 netif_rx( skb );
1495 else
1496 netif_rx_ni( skb );
1497
1498 /* Enable Queues which we have disabled earlier */
1499 netif_tx_start_all_queues( pAdapter->dev );
1500
1501}
1502#endif // CONFIG_CFG80211