blob: 72cc77dae32746afef2def5f9cf48a1d52b3de02 [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"
60
61#include <linux/netdevice.h>
62#include <linux/skbuff.h>
63#include <linux/etherdevice.h>
64#include <net/ieee80211_radiotap.h>
Hoonki Lee1090c6a2013-01-16 17:40:54 -080065#ifdef FEATURE_WLAN_TDLS
66#include "wlan_hdd_tdls.h"
67#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070068
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080069//Ms to Micro Sec
70#define MS_TO_MUS(x) ((x)*1000);
71
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070072#ifdef WLAN_FEATURE_P2P_DEBUG
73#define MAX_P2P_ACTION_FRAME_TYPE 9
74const char *p2p_action_frame_type[]={"GO Negotiation Request",
75 "GO Negotiation Response",
76 "GO Negotiation Confirmation",
77 "P2P Invitation Request",
78 "P2P Invitation Response",
79 "Device Discoverability Request",
80 "Device Discoverability Response",
81 "Provision Discovery Request",
82 "Provision Discovery Response"};
83
84/* We no need to protect this variable since
85 * there is no chance of race to condition
86 * and also not make any complicating the code
87 * just for debugging log
88 */
89tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
90
91#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -080092#ifdef WLAN_FEATURE_TDLS_DEBUG
93#define MAX_TDLS_ACTION_FRAME_TYPE 11
94const char *tdls_action_frame_type[] = {"TDLS Setup Request",
95 "TDLS Setup Response",
96 "TDLS Setup Confirm",
97 "TDLS Teardown",
98 "TDLS Peer Traffic Indication",
99 "TDLS Channel Switch Request",
100 "TDLS Channel Switch Response",
101 "TDLS Peer PSM Request",
102 "TDLS Peer PSM Response",
103 "TDLS Peer Traffic Response",
104 "TDLS Discovery Request" };
105#endif
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700106
Jeff Johnson295189b2012-06-20 16:38:30 -0700107extern struct net_device_ops net_ops_struct;
108
109static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
110 int rtap_len, int flag );
111
112static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
113 hdd_cfg80211_state_t* cfgState,
114 tANI_BOOLEAN actionSendSuccess );
115
116static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
117 tANI_U32 nFrameLength,
118 tANI_U8* pbFrames,
119 tANI_U8 frameType );
120
Jeff Johnson295189b2012-06-20 16:38:30 -0700121eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
122 eHalStatus status )
123{
124 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700125 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
126 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
127
128 if( pRemainChanCtx == NULL )
129 {
130 hddLog( LOGW,
131 "%s: No Rem on channel pending for which Rsp is received", __func__);
132 return eHAL_STATUS_SUCCESS;
133 }
134
135 hddLog( LOG1, "Received remain on channel rsp");
136
137 cfgState->remain_on_chan_ctx = NULL;
138
139 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
140 {
141 if( cfgState->buf )
142 {
143 hddLog( LOGP,
144 "%s: We need to receive yet an ack from one of tx packet",
145 __func__);
146 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800147 cfg80211_remain_on_channel_expired(
148#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
149 pRemainChanCtx->dev->ieee80211_ptr,
150#else
151 pRemainChanCtx->dev,
152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700153 pRemainChanCtx->cookie,
154 &pRemainChanCtx->chan,
155 pRemainChanCtx->chan_type, GFP_KERNEL );
156 }
157
Jeff Johnson295189b2012-06-20 16:38:30 -0700158
159 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700160 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
161 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700162 )
163 {
164 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800165 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
166 {
167 sme_DeregisterMgmtFrame(
168 hHal, sessionId,
169 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
170 NULL, 0 );
171 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700172 }
173 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
174 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
175 )
176 {
177 WLANSAP_DeRegisterMgmtFrame(
178 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
179 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
180 NULL, 0 );
181 }
182
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800183 vos_mem_free( pRemainChanCtx );
Jeff Johnson295189b2012-06-20 16:38:30 -0700184 complete(&pAdapter->cancel_rem_on_chan_var);
185 return eHAL_STATUS_SUCCESS;
186}
187
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -0800188void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700189{
Jeff Johnson295189b2012-06-20 16:38:30 -0700190 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
191 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700192
Jeff Johnson32d95a32012-09-10 13:15:23 -0700193 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700194 {
Jeff Johnson32d95a32012-09-10 13:15:23 -0700195 hddLog( LOG1, "Cancel Existing Remain on Channel");
196
197 /* Wait till remain on channel ready indication before issuing cancel
198 * remain on channel request, otherwise if remain on channel not
199 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700200 * will be in unknown state.
201 */
202 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
203 msecs_to_jiffies(WAIT_REM_CHAN_READY));
204 if (!status)
205 {
206 hddLog( LOGE,
207 "%s: timeout waiting for remain on channel ready indication",
208 __func__);
209 }
210
211 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700212
Jeff Johnson295189b2012-06-20 16:38:30 -0700213 /* Issue abort remain on chan request to sme.
214 * The remain on channel callback will make sure the remain_on_chan
215 * expired event is sent.
216 */
217 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700218 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
219 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700220 )
221 {
222 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
223 pAdapter->sessionId );
224 }
225 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
226 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
227 )
228 {
229 WLANSAP_CancelRemainOnChannel(
230 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
231 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700232
Jeff Johnson32d95a32012-09-10 13:15:23 -0700233 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700234 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700235
236 if (!status)
237 {
238 hddLog( LOGE,
239 "%s: timeout waiting for cancel remain on channel ready indication",
240 __func__);
241 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700242 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700243}
244
245int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
246{
247 int status = 0;
248 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
249
250 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
251 {
252 //Cancel Existing Remain On Channel
253 //If no action frame is pending
254 if( cfgState->remain_on_chan_ctx != NULL)
255 {
256 //Check whether Action Frame is pending or not
257 if( cfgState->buf == NULL)
258 {
259 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
260 }
261 else
262 {
263 hddLog( LOG1, "Cannot Cancel Existing Remain on Channel");
264 status = -EBUSY;
265 }
266 }
267 }
268 return status;
269}
270
271static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
272 struct net_device *dev,
273 struct ieee80211_channel *chan,
274 enum nl80211_channel_type channel_type,
275 unsigned int duration, u64 *cookie,
276 rem_on_channel_request_type_t request_type )
277{
278 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
279 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
280 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
281 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
282 __func__,pAdapter->device_mode);
283
284 hddLog( LOG1,
285 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d",
286 chan->hw_value, chan->center_freq, channel_type, duration );
287
288 //Cancel existing remain On Channel if any
289 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700290
Jeff Johnsone7245742012-09-05 17:12:55 -0700291 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700293 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700294 * channel requets when Load/Unload is in progress*/
295 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
296 {
297 hddLog( LOGE,
298 "%s: Wlan Load/Unload is in progress", __func__);
299 return -EBUSY;
300 }
301
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700302 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
303 {
304 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
305 "%s:LOGP in Progress. Ignore!!!", __func__);
306 return -EAGAIN;
307 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
309 if( NULL == pRemainChanCtx )
310 {
311 hddLog(VOS_TRACE_LEVEL_FATAL,
312 "%s: Not able to allocate memory for Channel context",
313 __func__);
314 return -ENOMEM;
315 }
316
317 vos_mem_copy( &pRemainChanCtx->chan, chan,
318 sizeof(struct ieee80211_channel) );
319
320 pRemainChanCtx->chan_type = channel_type;
321 pRemainChanCtx->duration = duration;
322 pRemainChanCtx->dev = dev;
323 *cookie = (tANI_U32) pRemainChanCtx;
324 pRemainChanCtx->cookie = *cookie;
325 pRemainChanCtx->rem_on_chan_request = request_type;
326 cfgState->remain_on_chan_ctx = pRemainChanCtx;
327 cfgState->current_freq = chan->center_freq;
328
329 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
330
331 //call sme API to start remain on channel.
332 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700333 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
334 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700335 )
336 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700337 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700338 //call sme API to start remain on channel.
339 sme_RemainOnChannel(
340 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
341 chan->hw_value, duration,
342 wlan_hdd_remain_on_channel_callback, pAdapter );
343
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800344 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
345 {
346 sme_RegisterMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
347 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
348 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 );
349 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700350
351 }
352 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
353 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
354 )
355 {
356 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700357 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700358 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
359 chan->hw_value, duration,
360 wlan_hdd_remain_on_channel_callback, pAdapter ))
361
362 {
363 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
364 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
365 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700366 vos_mem_free (pRemainChanCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700367 return -EINVAL;
368 }
369
370
Jeff Johnson43971f52012-07-17 12:26:56 -0700371 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700372 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
373 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
374 NULL, 0 ))
375 {
376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
377 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
378 WLANSAP_CancelRemainOnChannel(
379 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
380 return -EINVAL;
381 }
382
383 }
384 return 0;
385
386}
387
388int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800389#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
390 struct wireless_dev *wdev,
391#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700392 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800393#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700394 struct ieee80211_channel *chan,
395 enum nl80211_channel_type channel_type,
396 unsigned int duration, u64 *cookie )
397{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800398#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
399 struct net_device *dev = wdev->netdev;
400#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700401 return wlan_hdd_request_remain_on_channel(wiphy, dev,
402 chan, channel_type, duration, cookie,
403 REMAIN_ON_CHANNEL_REQUEST);
404}
405
406void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
407{
408 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
409 hdd_remain_on_chan_ctx_t* pRemainChanCtx = cfgState->remain_on_chan_ctx;
410
411 hddLog( LOG1, "Ready on chan ind");
412
413 if( pRemainChanCtx != NULL )
414 {
415 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
416 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800417 cfg80211_ready_on_channel(
418#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
419 pAdapter->dev->ieee80211_ptr,
420#else
421 pAdapter->dev,
422#endif
423 (tANI_U32)pRemainChanCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -0700424 &pRemainChanCtx->chan, pRemainChanCtx->chan_type,
425 pRemainChanCtx->duration, GFP_KERNEL );
426 }
427#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
428 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request )
429 {
430 complete(&pAdapter->offchannel_tx_event);
431 }
432#endif
433 complete(&pAdapter->rem_on_chan_ready_event);
434 }
435 else
436 {
437 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
438 }
439 return;
440}
441
442int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800443#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
444 struct wireless_dev *wdev,
445#else
446 struct net_device *dev,
447#endif
448 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700449{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800450#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
451 struct net_device *dev = wdev->netdev;
452#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700453 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700454 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
455 int status = 0;
456
457 hddLog( LOG1, "Cancel remain on channel req");
458
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700459 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
460 {
461 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
462 "%s:LOGP in Progress. Ignore!!!", __func__);
463 return -EAGAIN;
464 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700465 /* FIXME cancel currently running remain on chan.
466 * Need to check cookie and cancel accordingly
467 */
468 if( (cfgState->remain_on_chan_ctx == NULL) ||
469 (cfgState->remain_on_chan_ctx->cookie != cookie) )
470 {
471 hddLog( LOGE,
472 "%s: No Remain on channel pending with specified cookie value",
473 __func__);
474 return -EINVAL;
475 }
476
477 /* wait until remain on channel ready event received
478 * for already issued remain on channel request */
479 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
480 msecs_to_jiffies(WAIT_REM_CHAN_READY));
481 if (!status)
482 {
483 hddLog( LOGE,
484 "%s: timeout waiting for remain on channel ready indication",
485 __func__);
486 }
487 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
488 /* Issue abort remain on chan request to sme.
489 * The remain on channel callback will make sure the remain_on_chan
490 * expired event is sent.
491 */
492 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700493 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
494 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700495 )
496 {
497 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700498 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
499 sessionId );
500 }
501 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
502 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
503 )
504 {
505 WLANSAP_CancelRemainOnChannel(
506 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
507 }
508 else
509 {
510 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
511 __func__, pAdapter->device_mode);
512 return -EIO;
513 }
514 wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
515 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
516 return 0;
517}
518
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800519#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
520int wlan_hdd_action( struct wiphy *wiphy, struct wireless_dev *wdev,
521 struct ieee80211_channel *chan, bool offchan,
522 enum nl80211_channel_type channel_type,
523 bool channel_type_valid, unsigned int wait,
524 const u8 *buf, size_t len, bool no_cck,
525 bool dont_wait_for_ack, u64 *cookie )
526#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700527int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
528 struct ieee80211_channel *chan, bool offchan,
529 enum nl80211_channel_type channel_type,
530 bool channel_type_valid, unsigned int wait,
531 const u8 *buf, size_t len, bool no_cck,
532 bool dont_wait_for_ack, u64 *cookie )
533#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
534int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
535 struct ieee80211_channel *chan, bool offchan,
536 enum nl80211_channel_type channel_type,
537 bool channel_type_valid, unsigned int wait,
538 const u8 *buf, size_t len, u64 *cookie )
539#else
540int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
541 struct ieee80211_channel *chan,
542 enum nl80211_channel_type channel_type,
543 bool channel_type_valid,
544 const u8 *buf, size_t len, u64 *cookie )
545#endif //LINUX_VERSION_CODE
546{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800547#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
548 struct net_device *dev = wdev->netdev;
549#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700550 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
551 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700552 tANI_U16 extendedWait = 0;
553 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
554 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
555 tActionFrmType actionFrmType;
556 bool noack = 0;
Chet Lanctot186b5732013-03-18 10:26:30 -0700557#ifdef WLAN_FEATURE_11W
558 tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit
559#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700560
Jeff Johnson295189b2012-06-20 16:38:30 -0700561#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
562 hdd_adapter_t *goAdapter;
563#endif
564
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800565 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
566 {
567 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
568 "%s:LOGP in Progress. Ignore!!!", __func__);
569 return -EBUSY;
570 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700571#ifdef WLAN_FEATURE_P2P_DEBUG
572 if ((type == SIR_MAC_MGMT_FRAME) &&
573 (subType == SIR_MAC_MGMT_ACTION) &&
574 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
575 {
576 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800577 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700578 {
579 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
580 actionFrmType);
581 }
582 else
583 {
584 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
585 p2p_action_frame_type[actionFrmType]);
586 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
587 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
588 {
589 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
590 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800591 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700592 }
593 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
594 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
595 {
596 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
597 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
598 " completed state");
599 }
600 }
601 }
602#endif
603
Jeff Johnsone7245742012-09-05 17:12:55 -0700604#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
605 noack = dont_wait_for_ack;
606#endif
607
608 //If the wait is coming as 0 with off channel set
609 //then set the wait to 200 ms
610 if (offchan && !wait)
611 wait = ACTION_FRAME_DEFAULT_WAIT;
612
Jeff Johnson295189b2012-06-20 16:38:30 -0700613 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
614 __func__,pAdapter->device_mode);
615
616 //Call sme API to send out a action frame.
617 // OR can we send it directly through data path??
618 // After tx completion send tx status back.
619 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
620 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
621 )
622 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700623 if (type == SIR_MAC_MGMT_FRAME)
624 {
625 if (subType == SIR_MAC_MGMT_PROBE_RSP)
626 {
627 /* Drop Probe response recieved from supplicant, as for GO and
628 SAP PE itself sends probe response
629 */
630 goto err_rem_channel;
631 }
632 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
633 (subType == SIR_MAC_MGMT_DEAUTH))
634 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700635 /* During EAP failure or P2P Group Remove supplicant
636 * is sending del_station command to driver. From
637 * del_station function, Driver will send deauth frame to
638 * p2p client. No need to send disassoc frame from here.
639 * so Drop the frame here and send tx indication back to
640 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700641 */
642 tANI_U8 dstMac[ETH_ALEN] = {0};
643 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700644 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700645 "%s: Deauth/Disassoc received for STA:"
Jeff Johnsone7245742012-09-05 17:12:55 -0700646 "%02x:%02x:%02x:%02x:%02x:%02x",
647 __func__,
648 dstMac[0], dstMac[1], dstMac[2],
Jeff Johnson295189b2012-06-20 16:38:30 -0700649 dstMac[3], dstMac[4], dstMac[5]);
Jeff Johnson295189b2012-06-20 16:38:30 -0700650 goto err_rem_channel;
651 }
652 }
653 }
654
655 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800656 {
657 if ( !noack )
658 {
659 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
660 __func__);
661 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
662 }
663 else
664 {
665 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
666 __func__);
667 return -EBUSY;
668 }
669 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700670
671 hddLog( LOG1, "Action frame tx request");
672
673#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
674 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
675
676 //If GO adapter exists and operating on same frequency
677 //then we will not request remain on channel
678 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
679 == goAdapter->sessionCtx.ap.operatingChannel ) )
680 {
681 goto send_frame;
682 }
683#endif
684
685#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
686 if( offchan && wait)
687 {
688 int status;
689
690 // In case of P2P Client mode if we are already
691 // on the same channel then send the frame directly
692
693 if((cfgState->remain_on_chan_ctx != NULL) &&
694 (cfgState->current_freq == chan->center_freq)
695 )
696 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700697 hddLog(LOG1,"action frame: extending the wait time\n");
698 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700699 goto send_frame;
700 }
701
702 INIT_COMPLETION(pAdapter->offchannel_tx_event);
703
704 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
705 chan, channel_type, wait, cookie,
706 OFF_CHANNEL_ACTION_TX);
707
708 if(0 != status)
709 {
710 if( (-EBUSY == status) &&
711 (cfgState->current_freq == chan->center_freq) )
712 {
713 goto send_frame;
714 }
715 goto err_rem_channel;
716 }
717
718 /* Wait for driver to be ready on the requested channel */
719 status = wait_for_completion_interruptible_timeout(
720 &pAdapter->offchannel_tx_event,
721 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
722 if(!status)
723 {
724 hddLog( LOGE, "Not able to complete remain on channel request"
725 " within timeout period");
726 goto err_rem_channel;
727 }
728 }
729 else if ( offchan )
730 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700731 /* Check before sending action frame
732 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -0700733 if(NULL == cfgState->remain_on_chan_ctx)
734 {
735 goto err_rem_channel;
736 }
737 }
738 send_frame:
739#endif
740
Jeff Johnsone7245742012-09-05 17:12:55 -0700741 if(!noack)
742 {
743 cfgState->buf = vos_mem_malloc( len ); //buf;
744 if( cfgState->buf == NULL )
745 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -0700746
Jeff Johnsone7245742012-09-05 17:12:55 -0700747 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -0700748
Jeff Johnsone7245742012-09-05 17:12:55 -0700749 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700750
751#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700752 if( cfgState->remain_on_chan_ctx )
753 {
754 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
755 *cookie = cfgState->action_cookie;
756 }
757 else
758 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700759#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700760 *cookie = (tANI_U32) cfgState->buf;
761 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -0700762#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700763 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700764#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700765 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700766
767 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700768 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
769 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700770 )
771 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700772 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800773
Jeff Johnsone7245742012-09-05 17:12:55 -0700774 if ((type == SIR_MAC_MGMT_FRAME) &&
775 (subType == SIR_MAC_MGMT_ACTION) &&
776 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -0700777 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700778 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
779 hddLog(LOG1, "Tx Action Frame %u \n", actionFrmType);
780 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -0700781 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700782 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
783 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING \n", __func__);
784 }
785 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
786 {
787 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
788 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700789 }
790 }
Chet Lanctot186b5732013-03-18 10:26:30 -0700791#ifdef WLAN_FEATURE_11W
792 if ((type == SIR_MAC_MGMT_FRAME) &&
793 (subType == SIR_MAC_MGMT_ACTION) &&
794 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME))
795 {
796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
797 "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query");
798 // Since this is an SA Query Action Frame, we have to protect it
799 WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]);
800 }
801#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700802 if (eHAL_STATUS_SUCCESS !=
803 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -0700804 sessionId, buf, len, extendedWait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -0700805 {
806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
807 "%s: sme_sendAction returned fail", __func__);
808 goto err;
809 }
810 }
811 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
812 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
813 )
814 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700815 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700816 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700817 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700818 {
819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
820 "%s: WLANSAP_SendAction returned fail", __func__);
821 goto err;
822 }
823 }
824
825 return 0;
826err:
Jeff Johnsone7245742012-09-05 17:12:55 -0700827 if(!noack)
828 {
829 hdd_sendActionCnf( pAdapter, FALSE );
830 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700831 return 0;
832err_rem_channel:
833 *cookie = (tANI_U32)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800834 cfg80211_mgmt_tx_status(
835#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
836 pAdapter->dev->ieee80211_ptr,
837#else
838 pAdapter->dev,
839#endif
840 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -0700841 return 0;
842}
843
844#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800845#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
846int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
847 struct wireless_dev *wdev,
848 u64 cookie)
849{
850 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
851}
852#else
853int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -0700854 struct net_device *dev,
855 u64 cookie)
856{
857 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
858}
859#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800860#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700861
862void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
863{
864 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
865
Jeff Johnsone7245742012-09-05 17:12:55 -0700866 cfgState->actionFrmState = HDD_IDLE;
867
Jeff Johnson295189b2012-06-20 16:38:30 -0700868 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
869 if( NULL == cfgState->buf )
870 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700871 return;
872 }
873
874 /* If skb is NULL it means this packet was received on CFG80211 interface
875 * else it was received on Monitor interface */
876 if( cfgState->skb == NULL )
877 {
878 /*
879 * buf is the same pointer it passed us to send. Since we are sending
880 * it through control path, we use different buffers.
881 * In case of mac80211, they just push it to the skb and pass the same
882 * data while sending tx ack status.
883 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800884 cfg80211_mgmt_tx_status(
885#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
886 pAdapter->dev->ieee80211_ptr,
887#else
888 pAdapter->dev,
889#endif
890 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700891 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
892 vos_mem_free( cfgState->buf );
893 cfgState->buf = NULL;
894 }
895 else
896 {
897 hdd_adapter_t* pMonAdapter =
898 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
899 if( pMonAdapter == NULL )
900 {
901 hddLog( LOGE, "Not able to get Monitor Adapter");
902 cfgState->skb = NULL;
903 vos_mem_free( cfgState->buf );
904 cfgState->buf = NULL;
905 complete(&pAdapter->tx_action_cnf_event);
906 return;
907 }
908 /* Send TX completion feedback over monitor interface. */
909 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
910 cfgState->skb = NULL;
911 vos_mem_free( cfgState->buf );
912 cfgState->buf = NULL;
913 /* Look for the next Mgmt packet to TX */
914 hdd_mon_tx_mgmt_pkt(pAdapter);
915 }
916 complete(&pAdapter->tx_action_cnf_event);
917}
918
919/**
920 * hdd_setP2pNoa
921 *
922 *FUNCTION:
923 * This function is called from hdd_hostapd_ioctl function when Driver
924 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
925 *
926 *LOGIC:
927 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
928 *
929 *ASSUMPTIONS:
930 *
931 *
932 *NOTE:
933 *
934 * @param dev Pointer to net device structure
935 * @param command Pointer to command
936 *
937 * @return Status
938 */
939
940int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
941{
942 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
943 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
944 VOS_STATUS status = VOS_STATUS_SUCCESS;
945 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800946 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -0700947 char *param;
948
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -0800949 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -0700950 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800951 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700952 param++;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800953 sscanf(param, "%d %d %d", &count, &start_time, &duration);
Jeff Johnson295189b2012-06-20 16:38:30 -0700954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
955 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d \n",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800956 __func__, count, start_time, duration);
957 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -0700958 /* PS Selection
959 * Periodic NoA (2)
960 * Single NOA (4)
961 */
962 NoA.opp_ps = 0;
963 NoA.ctWindow = 0;
964 if (count == 1)
965 {
966 NoA.duration = 0;
967 NoA.single_noa_duration = duration;
968 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
969 }
970 else
971 {
972 NoA.duration = duration;
973 NoA.single_noa_duration = 0;
974 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
975 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800976 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -0700977 NoA.count = count;
978 NoA.sessionid = pAdapter->sessionId;
979
980 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
981 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
982 "interval %d count %d single noa duration %d "
983 "PsSelection %x \n", __func__, NoA.opp_ps,
984 NoA.ctWindow, NoA.duration, NoA.interval,
985 NoA.count, NoA.single_noa_duration,
986 NoA.psSelection);
987
988 sme_p2pSetPs(hHal, &NoA);
989 return status;
990}
991
992/**
993 * hdd_setP2pOpps
994 *
995 *FUNCTION:
996 * This function is called from hdd_hostapd_ioctl function when Driver
997 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
998 *
999 *LOGIC:
1000 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1001 *
1002 *ASSUMPTIONS:
1003 *
1004 *
1005 *NOTE:
1006 *
1007 * @param dev Pointer to net device structure
1008 * @param command Pointer to command
1009 *
1010 * @return Status
1011 */
1012
1013int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1014{
1015 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1016 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1017 VOS_STATUS status = VOS_STATUS_SUCCESS;
1018 tP2pPsConfig NoA;
1019 char *param;
1020 int legacy_ps, opp_ps, ctwindow;
1021
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001022 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001023 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001024 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001025 param++;
1026 sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1027 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1028 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1029 __func__, legacy_ps, opp_ps, ctwindow);
1030
1031 /* PS Selection
1032 * Opportunistic Power Save (1)
1033 */
1034
1035 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1036 * When user want to set ctWindow during that time other parameters
1037 * values are coming from wpa_supplicant as -1.
1038 * Example : User want to set ctWindow with 30 then wpa_cli command :
1039 * P2P_SET ctwindow 30
1040 * Command Received at hdd_hostapd_ioctl is as below:
1041 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
1042 */
1043 if (ctwindow != -1)
1044 {
1045
1046 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1047 "Opportunistic Power Save is %s \n",
1048 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1049
1050 if (ctwindow != pAdapter->ctw)
1051 {
1052 pAdapter->ctw = ctwindow;
1053
1054 if(pAdapter->ops)
1055 {
1056 NoA.opp_ps = pAdapter->ops;
1057 NoA.ctWindow = pAdapter->ctw;
1058 NoA.duration = 0;
1059 NoA.single_noa_duration = 0;
1060 NoA.interval = 0;
1061 NoA.count = 0;
1062 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1063 NoA.sessionid = pAdapter->sessionId;
1064
1065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1066 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1067 "interval %d count %d single noa duration %d "
1068 "PsSelection %x \n", __func__, NoA.opp_ps,
1069 NoA.ctWindow, NoA.duration, NoA.interval,
1070 NoA.count, NoA.single_noa_duration,
1071 NoA.psSelection);
1072
1073 sme_p2pSetPs(hHal, &NoA);
1074 }
1075 return 0;
1076 }
1077 }
1078
1079 if (opp_ps != -1)
1080 {
1081 pAdapter->ops = opp_ps;
1082
1083 if ((opp_ps != -1) && (pAdapter->ctw))
1084 {
1085 NoA.opp_ps = opp_ps;
1086 NoA.ctWindow = pAdapter->ctw;
1087 NoA.duration = 0;
1088 NoA.single_noa_duration = 0;
1089 NoA.interval = 0;
1090 NoA.count = 0;
1091 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1092 NoA.sessionid = pAdapter->sessionId;
1093
1094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1095 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1096 "interval %d count %d single noa duration %d "
1097 "PsSelection %x \n", __func__, NoA.opp_ps,
1098 NoA.ctWindow, NoA.duration, NoA.interval,
1099 NoA.count, NoA.single_noa_duration,
1100 NoA.psSelection);
1101
1102 sme_p2pSetPs(hHal, &NoA);
1103 }
1104 }
1105 return status;
1106}
1107
1108int hdd_setP2pPs( struct net_device *dev, void *msgData )
1109{
1110 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1111 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1112 VOS_STATUS status = VOS_STATUS_SUCCESS;
1113 tP2pPsConfig NoA;
1114 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1115
1116 NoA.opp_ps = pappNoA->opp_ps;
1117 NoA.ctWindow = pappNoA->ctWindow;
1118 NoA.duration = pappNoA->duration;
1119 NoA.interval = pappNoA->interval;
1120 NoA.count = pappNoA->count;
1121 NoA.single_noa_duration = pappNoA->single_noa_duration;
1122 NoA.psSelection = pappNoA->psSelection;
1123 NoA.sessionid = pAdapter->sessionId;
1124
1125 sme_p2pSetPs(hHal, &NoA);
1126 return status;
1127}
Jeff Johnson295189b2012-06-20 16:38:30 -07001128
1129static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1130{
1131 tANI_U8 sessionType;
1132
1133 switch( type )
1134 {
1135 case NL80211_IFTYPE_AP:
1136 sessionType = WLAN_HDD_SOFTAP;
1137 break;
1138 case NL80211_IFTYPE_P2P_GO:
1139 sessionType = WLAN_HDD_P2P_GO;
1140 break;
1141 case NL80211_IFTYPE_P2P_CLIENT:
1142 sessionType = WLAN_HDD_P2P_CLIENT;
1143 break;
1144 case NL80211_IFTYPE_STATION:
1145 sessionType = WLAN_HDD_INFRA_STATION;
1146 break;
1147 case NL80211_IFTYPE_MONITOR:
1148 sessionType = WLAN_HDD_MONITOR;
1149 break;
1150 default:
1151 sessionType = WLAN_HDD_INFRA_STATION;
1152 break;
1153 }
1154
1155 return sessionType;
1156}
1157
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001158#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1159struct wireless_dev* wlan_hdd_add_virtual_intf(
1160 struct wiphy *wiphy, const char *name,
1161 enum nl80211_iftype type,
1162 u32 *flags, struct vif_params *params )
1163#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1164struct wireless_dev* wlan_hdd_add_virtual_intf(
1165 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1166 u32 *flags, struct vif_params *params )
1167#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001168struct net_device* wlan_hdd_add_virtual_intf(
1169 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1170 u32 *flags, struct vif_params *params )
1171#else
1172int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1173 enum nl80211_iftype type,
1174 u32 *flags, struct vif_params *params )
1175#endif
1176{
1177 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1178 hdd_adapter_t* pAdapter = NULL;
1179
1180 ENTER();
1181
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001182 if(hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
1183 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001184 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001185 "interfaces of same type are not supported currently.",__func__, type);
Jeff Johnsond13512a2012-07-17 11:42:19 -07001186 return NULL;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001187 }
1188
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001189 if (pHddCtx->isLogpInProgress)
1190 {
1191 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1192 "%s:LOGP in Progress. Ignore!!!", __func__);
1193#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1194 return NULL;
1195#else
1196 return -EAGAIN;
1197#endif
1198 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001199 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
1200 {
1201 if( (NL80211_IFTYPE_P2P_GO == type) ||
1202 (NL80211_IFTYPE_P2P_CLIENT == type) )
1203 {
1204 /* Generate the P2P Interface Address. this address must be
1205 * different from the P2P Device Address.
1206 */
1207 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1208 p2pDeviceAddress.bytes[4] ^= 0x80;
1209 pAdapter = hdd_open_adapter( pHddCtx,
1210 wlan_hdd_get_session_type(type),
1211 name, p2pDeviceAddress.bytes,
1212 VOS_TRUE );
1213 }
1214 }
1215 else
1216 {
1217 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1218 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1219 }
1220
1221 if( NULL == pAdapter)
1222 {
1223 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1224#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1225 return NULL;
1226#else
1227 return -EINVAL;
1228#endif
1229 }
1230 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001231#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1232 return pAdapter->dev->ieee80211_ptr;
1233#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001234 return pAdapter->dev;
1235#else
1236 return 0;
1237#endif
1238}
1239
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001240#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1241int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1242#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001243int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001244#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001245{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001246#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1247 struct net_device *dev = wdev->netdev;
1248#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001249 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1250 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1251 ENTER();
1252
1253 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1254 __func__,pVirtAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001255 if (pHddCtx->isLogpInProgress)
1256 {
1257 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1258 "%s:LOGP in Progress. Ignore!!!", __func__);
1259 return -EAGAIN;
1260 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001261
1262 wlan_hdd_release_intf_addr( pHddCtx,
1263 pVirtAdapter->macAddressCurrent.bytes );
1264
1265 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1266 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1267 EXIT();
1268 return 0;
1269}
1270
1271void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001272 tANI_U32 nFrameLength,
1273 tANI_U8* pbFrames,
Jeff Johnson295189b2012-06-20 16:38:30 -07001274 tANI_U8 frameType )
1275{
1276 //Indicate a Frame over Monitor Intf.
1277 int rxstat;
1278 struct sk_buff *skb = NULL;
1279 int needed_headroom = 0;
1280 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1281 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001282#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001283#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1284 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1285#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001286#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001287 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1288
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001289 if (NULL == pbFrames)
1290 {
1291 hddLog(LOGE, FL("NULL frame pointer"));
1292 return;
1293 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001294
1295 /* room for the radiotap header based on driver features
1296 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1297 * RX flags.
1298 * */
1299 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1300
1301 //alloc skb here
1302 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1303 if (unlikely(NULL == skb))
1304 {
1305 hddLog( LOGW, FL("Unable to allocate skb"));
1306 return;
1307 }
1308 skb_reserve(skb, VPKT_SIZE_BUFFER);
1309 if (unlikely(skb_headroom(skb) < nFrameLength))
1310 {
1311 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1312 "HDD [%d]: Insufficient headroom, "
1313 "head[%p], data[%p], req[%d]",
1314 __LINE__, skb->head, skb->data, nFrameLength);
1315 kfree_skb(skb);
1316 return ;
1317 }
1318 // actually push the data
1319 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1320 /* prepend radiotap information */
1321 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1322 {
1323 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1324 //free skb
1325 kfree_skb(skb);
1326 return ;
1327 }
1328
1329 skb_reset_mac_header( skb );
1330 skb->dev = pMonAdapter->dev;
1331 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001332 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001333#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001334#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1335 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1336#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001337#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001338 rxstat = netif_rx_ni(skb);
1339 if( NET_RX_SUCCESS == rxstat )
1340 {
1341 hddLog( LOG1, FL("Success"));
1342 }
1343 else
1344 hddLog( LOGE, FL("Failed %d"), rxstat);
1345
1346 return ;
1347}
1348
1349void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
1350 tANI_U32 nFrameLength,
1351 tANI_U8* pbFrames,
1352 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301353 tANI_U32 rxChan,
1354 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001355{
1356 tANI_U16 freq;
Jeff Johnsone7245742012-09-05 17:12:55 -07001357 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001358 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001359 tActionFrmType actionFrmType;
1360 hdd_cfg80211_state_t *cfgState = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001361
1362 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d\n",
1363 __func__, frameType, nFrameLength);
1364
1365 if (NULL == pAdapter)
1366 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001367 hddLog(LOGE, FL("pAdapter is NULL"));
1368 return;
1369 }
1370
1371 if (0 == nFrameLength)
1372 {
1373 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
1374 return;
1375 }
1376
1377 if (NULL == pbFrames)
1378 {
1379 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001380 return;
1381 }
1382
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001383 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1384 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1385
1386 /* Get pAdapter from Destination mac address of the frame */
1387 if ((type == SIR_MAC_MGMT_FRAME) &&
1388 (subType != SIR_MAC_MGMT_PROBE_REQ))
1389 {
1390 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1391 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1392 if (NULL == pAdapter)
1393 {
1394 /* Under assumtion that we don't receive any action frame
1395 * with BCST as destination we dropping action frame
1396 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001397 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1398 MAC_ADDRESS_STR ,
1399 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1400 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
1401 " subType = %d \n",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001402 return;
1403 }
1404 }
1405
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001406
Jeff Johnson295189b2012-06-20 16:38:30 -07001407 if (NULL == pAdapter->dev)
1408 {
1409 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1410 return;
1411 }
1412
1413 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1414 {
1415 hddLog( LOGE, FL("pAdapter has invalid magic"));
1416 return;
1417 }
1418
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001419 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1420 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001421 {
1422 hdd_adapter_t *pMonAdapter =
1423 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1424
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001425 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001426 {
1427 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1428 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1429 pbFrames, frameType);
1430 return;
1431 }
1432 }
1433
1434 //Channel indicated may be wrong. TODO
1435 //Indicate an action frame.
1436 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1437 {
1438 freq = ieee80211_channel_to_frequency( rxChan,
1439 IEEE80211_BAND_2GHZ);
1440 }
1441 else
1442 {
1443 freq = ieee80211_channel_to_frequency( rxChan,
1444 IEEE80211_BAND_5GHZ);
1445 }
1446
Jeff Johnsone7245742012-09-05 17:12:55 -07001447 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1448
1449 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001450 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001451 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001452 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1453 {
1454 // public action frame
1455 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001456 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 -08001457 // P2P action frames
1458 {
1459 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
1460 hddLog(LOG1, "Rx Action Frame %u \n", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001461#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001462 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1463 {
1464 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1465 actionFrmType);
1466 }
1467 else
1468 {
1469 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1470 p2p_action_frame_type[actionFrmType]);
1471 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1472 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1473 {
1474 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1475 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001476 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001477 }
1478 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1479 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1480 {
1481 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001482 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1483 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001484 }
1485 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1486 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1487 {
1488 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1489 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1490 " completed state Autonomous GO formation");
1491 }
1492 }
1493#endif
1494
1495 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
1496 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
1497 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
1498 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
1499 {
1500 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
1501 __func__);
1502 hdd_sendActionCnf(pAdapter, TRUE);
1503 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001504 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001505#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001506 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 -07001507 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001508 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
1509#ifdef WLAN_FEATURE_TDLS_DEBUG
1510 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
1511 MAC_ADDR_ARRAY(mac),rxRssi);
1512#endif
1513 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
1514 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001515 }
1516#endif
1517 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001518#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001519 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
1520 {
1521 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
1522 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
1523 {
1524 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
1525 actionFrmType);
1526 }
1527 else
1528 {
1529 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
1530 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001531 }
1532 }
1533#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07001534 }
1535
Jeff Johnson295189b2012-06-20 16:38:30 -07001536 //Indicate Frame Over Normal Interface
1537 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
1538
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001539#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1540 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
1541 pbFrames, nFrameLength,
1542 GFP_ATOMIC );
1543#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001544 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
1545 pbFrames, nFrameLength,
1546 GFP_ATOMIC );
1547#else
1548 cfg80211_rx_mgmt( pAdapter->dev, freq,
1549 pbFrames, nFrameLength,
1550 GFP_ATOMIC );
1551#endif //LINUX_VERSION_CODE
1552}
1553
1554/*
1555 * ieee80211_add_rx_radiotap_header - add radiotap header
1556 */
1557static int hdd_wlan_add_rx_radiotap_hdr (
1558 struct sk_buff *skb, int rtap_len, int flag )
1559{
1560 u8 rtap_temp[20] = {0};
1561 struct ieee80211_radiotap_header *rthdr;
1562 unsigned char *pos;
1563 u16 rx_flags = 0;
1564
1565 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
1566
1567 /* radiotap header, set always present flags */
1568 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
1569 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
1570 rthdr->it_len = cpu_to_le16(rtap_len);
1571
1572 pos = (unsigned char *) (rthdr + 1);
1573
1574 /* the order of the following fields is important */
1575
1576 /* IEEE80211_RADIOTAP_FLAGS */
1577 *pos = 0;
1578 pos++;
1579
1580 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
1581 /* ensure 2 byte alignment for the 2 byte field as required */
1582 if ((pos - (u8 *)rthdr) & 1)
1583 pos++;
1584 put_unaligned_le16(rx_flags, pos);
1585 pos += 2;
1586
1587 // actually push the data
1588 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
1589
1590 return 0;
1591}
1592
1593static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
1594 hdd_cfg80211_state_t* cfgState,
1595 tANI_BOOLEAN actionSendSuccess )
1596{
1597 struct ieee80211_radiotap_header *rthdr;
1598 unsigned char *pos;
1599 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001600#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001601#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1602 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
1603#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001604#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001605
1606 /* 2 Byte for TX flags and 1 Byte for Retry count */
1607 u32 rtHdrLen = sizeof(*rthdr) + 3;
1608
1609 u8 *data;
1610
1611 /* We have to return skb with Data starting with MAC header. We have
1612 * copied SKB data starting with MAC header to cfgState->buf. We will pull
1613 * entire skb->len from skb and then we will push cfgState->buf to skb
1614 * */
1615 if( NULL == skb_pull(skb, skb->len) )
1616 {
1617 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
1618 kfree_skb(cfgState->skb);
1619 return;
1620 }
1621
1622 data = skb_push( skb, cfgState->len );
1623
1624 if (data == NULL)
1625 {
1626 hddLog( LOGE, FL("Not Able to Push %d byte to skb"), cfgState->len);
1627 kfree_skb( cfgState->skb );
1628 return;
1629 }
1630
1631 memcpy( data, cfgState->buf, cfgState->len );
1632
1633 /* send frame to monitor interfaces now */
1634 if( skb_headroom(skb) < rtHdrLen )
1635 {
1636 hddLog( LOGE, FL("No headroom for rtap header"));
1637 kfree_skb(cfgState->skb);
1638 return;
1639 }
1640
1641 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
1642
1643 memset( rthdr, 0, rtHdrLen );
1644 rthdr->it_len = cpu_to_le16( rtHdrLen );
1645 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
1646 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
1647 );
1648
1649 pos = (unsigned char *)( rthdr+1 );
1650
1651 // Fill TX flags
1652 *pos = actionSendSuccess;
1653 pos += 2;
1654
1655 // Fill retry count
1656 *pos = 0;
1657 pos++;
1658
1659 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001660 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 skb->pkt_type = PACKET_OTHERHOST;
1662 skb->protocol = htons(ETH_P_802_2);
1663 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001664#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001665#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1666 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1667#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001668#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001669 if (in_interrupt())
1670 netif_rx( skb );
1671 else
1672 netif_rx_ni( skb );
1673
1674 /* Enable Queues which we have disabled earlier */
1675 netif_tx_start_all_queues( pAdapter->dev );
1676
1677}