blob: f2a093fccb5a9cbbf2facb8bb5e7236575f09192 [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>
Hoonki Lee1090c6a2013-01-16 17:40:54 -080066#ifdef FEATURE_WLAN_TDLS
67#include "wlan_hdd_tdls.h"
68#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070069
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080070//Ms to Micro Sec
71#define MS_TO_MUS(x) ((x)*1000);
72
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070073#ifdef WLAN_FEATURE_P2P_DEBUG
74#define MAX_P2P_ACTION_FRAME_TYPE 9
75const char *p2p_action_frame_type[]={"GO Negotiation Request",
76 "GO Negotiation Response",
77 "GO Negotiation Confirmation",
78 "P2P Invitation Request",
79 "P2P Invitation Response",
80 "Device Discoverability Request",
81 "Device Discoverability Response",
82 "Provision Discovery Request",
83 "Provision Discovery Response"};
84
85/* We no need to protect this variable since
86 * there is no chance of race to condition
87 * and also not make any complicating the code
88 * just for debugging log
89 */
90tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
91
92#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -080093#ifdef WLAN_FEATURE_TDLS_DEBUG
94#define MAX_TDLS_ACTION_FRAME_TYPE 11
95const char *tdls_action_frame_type[] = {"TDLS Setup Request",
96 "TDLS Setup Response",
97 "TDLS Setup Confirm",
98 "TDLS Teardown",
99 "TDLS Peer Traffic Indication",
100 "TDLS Channel Switch Request",
101 "TDLS Channel Switch Response",
102 "TDLS Peer PSM Request",
103 "TDLS Peer PSM Response",
104 "TDLS Peer Traffic Response",
105 "TDLS Discovery Request" };
106#endif
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700107
Jeff Johnson295189b2012-06-20 16:38:30 -0700108extern struct net_device_ops net_ops_struct;
109
110static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
111 int rtap_len, int flag );
112
113static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
114 hdd_cfg80211_state_t* cfgState,
115 tANI_BOOLEAN actionSendSuccess );
116
117static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
118 tANI_U32 nFrameLength,
119 tANI_U8* pbFrames,
120 tANI_U8 frameType );
121
122#ifdef WLAN_FEATURE_P2P
123eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
124 eHalStatus status )
125{
126 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700127 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
128 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
129
130 if( pRemainChanCtx == NULL )
131 {
132 hddLog( LOGW,
133 "%s: No Rem on channel pending for which Rsp is received", __func__);
134 return eHAL_STATUS_SUCCESS;
135 }
136
137 hddLog( LOG1, "Received remain on channel rsp");
138
139 cfgState->remain_on_chan_ctx = NULL;
140
141 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
142 {
143 if( cfgState->buf )
144 {
145 hddLog( LOGP,
146 "%s: We need to receive yet an ack from one of tx packet",
147 __func__);
148 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800149 cfg80211_remain_on_channel_expired(
150#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
151 pRemainChanCtx->dev->ieee80211_ptr,
152#else
153 pRemainChanCtx->dev,
154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700155 pRemainChanCtx->cookie,
156 &pRemainChanCtx->chan,
157 pRemainChanCtx->chan_type, GFP_KERNEL );
158 }
159
Jeff Johnson295189b2012-06-20 16:38:30 -0700160
161 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700162 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
163 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700164 )
165 {
166 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800167 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
168 {
169 sme_DeregisterMgmtFrame(
170 hHal, sessionId,
171 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
172 NULL, 0 );
173 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700174 }
175 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
176 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
177 )
178 {
179 WLANSAP_DeRegisterMgmtFrame(
180 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
181 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
182 NULL, 0 );
183 }
184
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800185 vos_mem_free( pRemainChanCtx );
Jeff Johnson295189b2012-06-20 16:38:30 -0700186 complete(&pAdapter->cancel_rem_on_chan_var);
187 return eHAL_STATUS_SUCCESS;
188}
189
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -0800190void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700191{
Jeff Johnson295189b2012-06-20 16:38:30 -0700192 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
193 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700194
Jeff Johnson32d95a32012-09-10 13:15:23 -0700195 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700196 {
Jeff Johnson32d95a32012-09-10 13:15:23 -0700197 hddLog( LOG1, "Cancel Existing Remain on Channel");
198
199 /* Wait till remain on channel ready indication before issuing cancel
200 * remain on channel request, otherwise if remain on channel not
201 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700202 * will be in unknown state.
203 */
204 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
205 msecs_to_jiffies(WAIT_REM_CHAN_READY));
206 if (!status)
207 {
208 hddLog( LOGE,
209 "%s: timeout waiting for remain on channel ready indication",
210 __func__);
211 }
212
213 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700214
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 /* Issue abort remain on chan request to sme.
216 * The remain on channel callback will make sure the remain_on_chan
217 * expired event is sent.
218 */
219 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700220 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
221 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700222 )
223 {
224 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
225 pAdapter->sessionId );
226 }
227 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
228 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
229 )
230 {
231 WLANSAP_CancelRemainOnChannel(
232 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
233 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700234
Jeff Johnson32d95a32012-09-10 13:15:23 -0700235 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700236 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700237
238 if (!status)
239 {
240 hddLog( LOGE,
241 "%s: timeout waiting for cancel remain on channel ready indication",
242 __func__);
243 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700244 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700245}
246
247int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
248{
249 int status = 0;
250 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
251
252 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
253 {
254 //Cancel Existing Remain On Channel
255 //If no action frame is pending
256 if( cfgState->remain_on_chan_ctx != NULL)
257 {
258 //Check whether Action Frame is pending or not
259 if( cfgState->buf == NULL)
260 {
261 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
262 }
263 else
264 {
265 hddLog( LOG1, "Cannot Cancel Existing Remain on Channel");
266 status = -EBUSY;
267 }
268 }
269 }
270 return status;
271}
272
273static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
274 struct net_device *dev,
275 struct ieee80211_channel *chan,
276 enum nl80211_channel_type channel_type,
277 unsigned int duration, u64 *cookie,
278 rem_on_channel_request_type_t request_type )
279{
280 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
281 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
282 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
283 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
284 __func__,pAdapter->device_mode);
285
286 hddLog( LOG1,
287 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d",
288 chan->hw_value, chan->center_freq, channel_type, duration );
289
290 //Cancel existing remain On Channel if any
291 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700292
Jeff Johnsone7245742012-09-05 17:12:55 -0700293 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700294 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700295 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700296 * channel requets when Load/Unload is in progress*/
297 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
298 {
299 hddLog( LOGE,
300 "%s: Wlan Load/Unload is in progress", __func__);
301 return -EBUSY;
302 }
303
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700304 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
305 {
306 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
307 "%s:LOGP in Progress. Ignore!!!", __func__);
308 return -EAGAIN;
309 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
311 if( NULL == pRemainChanCtx )
312 {
313 hddLog(VOS_TRACE_LEVEL_FATAL,
314 "%s: Not able to allocate memory for Channel context",
315 __func__);
316 return -ENOMEM;
317 }
318
319 vos_mem_copy( &pRemainChanCtx->chan, chan,
320 sizeof(struct ieee80211_channel) );
321
322 pRemainChanCtx->chan_type = channel_type;
323 pRemainChanCtx->duration = duration;
324 pRemainChanCtx->dev = dev;
325 *cookie = (tANI_U32) pRemainChanCtx;
326 pRemainChanCtx->cookie = *cookie;
327 pRemainChanCtx->rem_on_chan_request = request_type;
328 cfgState->remain_on_chan_ctx = pRemainChanCtx;
329 cfgState->current_freq = chan->center_freq;
330
331 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
332
333 //call sme API to start remain on channel.
334 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700335 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
336 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700337 )
338 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700339 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700340 //call sme API to start remain on channel.
341 sme_RemainOnChannel(
342 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
343 chan->hw_value, duration,
344 wlan_hdd_remain_on_channel_callback, pAdapter );
345
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800346 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
347 {
348 sme_RegisterMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
349 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
350 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 );
351 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700352
353 }
354 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
355 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
356 )
357 {
358 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700359 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700360 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
361 chan->hw_value, duration,
362 wlan_hdd_remain_on_channel_callback, pAdapter ))
363
364 {
365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
366 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
367 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700368 vos_mem_free (pRemainChanCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700369 return -EINVAL;
370 }
371
372
Jeff Johnson43971f52012-07-17 12:26:56 -0700373 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700374 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
375 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
376 NULL, 0 ))
377 {
378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
379 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
380 WLANSAP_CancelRemainOnChannel(
381 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
382 return -EINVAL;
383 }
384
385 }
386 return 0;
387
388}
389
390int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800391#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
392 struct wireless_dev *wdev,
393#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700394 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800395#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700396 struct ieee80211_channel *chan,
397 enum nl80211_channel_type channel_type,
398 unsigned int duration, u64 *cookie )
399{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800400#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
401 struct net_device *dev = wdev->netdev;
402#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700403 return wlan_hdd_request_remain_on_channel(wiphy, dev,
404 chan, channel_type, duration, cookie,
405 REMAIN_ON_CHANNEL_REQUEST);
406}
407
408void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
409{
410 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
411 hdd_remain_on_chan_ctx_t* pRemainChanCtx = cfgState->remain_on_chan_ctx;
412
413 hddLog( LOG1, "Ready on chan ind");
414
415 if( pRemainChanCtx != NULL )
416 {
417 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
418 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800419 cfg80211_ready_on_channel(
420#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
421 pAdapter->dev->ieee80211_ptr,
422#else
423 pAdapter->dev,
424#endif
425 (tANI_U32)pRemainChanCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -0700426 &pRemainChanCtx->chan, pRemainChanCtx->chan_type,
427 pRemainChanCtx->duration, GFP_KERNEL );
428 }
429#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
430 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request )
431 {
432 complete(&pAdapter->offchannel_tx_event);
433 }
434#endif
435 complete(&pAdapter->rem_on_chan_ready_event);
436 }
437 else
438 {
439 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
440 }
441 return;
442}
443
444int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800445#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
446 struct wireless_dev *wdev,
447#else
448 struct net_device *dev,
449#endif
450 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700451{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800452#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
453 struct net_device *dev = wdev->netdev;
454#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700455 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700456 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
457 int status = 0;
458
459 hddLog( LOG1, "Cancel remain on channel req");
460
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700461 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
462 {
463 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
464 "%s:LOGP in Progress. Ignore!!!", __func__);
465 return -EAGAIN;
466 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700467 /* FIXME cancel currently running remain on chan.
468 * Need to check cookie and cancel accordingly
469 */
470 if( (cfgState->remain_on_chan_ctx == NULL) ||
471 (cfgState->remain_on_chan_ctx->cookie != cookie) )
472 {
473 hddLog( LOGE,
474 "%s: No Remain on channel pending with specified cookie value",
475 __func__);
476 return -EINVAL;
477 }
478
479 /* wait until remain on channel ready event received
480 * for already issued remain on channel request */
481 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
482 msecs_to_jiffies(WAIT_REM_CHAN_READY));
483 if (!status)
484 {
485 hddLog( LOGE,
486 "%s: timeout waiting for remain on channel ready indication",
487 __func__);
488 }
489 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
490 /* Issue abort remain on chan request to sme.
491 * The remain on channel callback will make sure the remain_on_chan
492 * expired event is sent.
493 */
494 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700495 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
496 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700497 )
498 {
499 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700500 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
501 sessionId );
502 }
503 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
504 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
505 )
506 {
507 WLANSAP_CancelRemainOnChannel(
508 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
509 }
510 else
511 {
512 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
513 __func__, pAdapter->device_mode);
514 return -EIO;
515 }
516 wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
517 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
518 return 0;
519}
520
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800521#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
522int wlan_hdd_action( struct wiphy *wiphy, struct wireless_dev *wdev,
523 struct ieee80211_channel *chan, bool offchan,
524 enum nl80211_channel_type channel_type,
525 bool channel_type_valid, unsigned int wait,
526 const u8 *buf, size_t len, bool no_cck,
527 bool dont_wait_for_ack, u64 *cookie )
528#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700529int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
530 struct ieee80211_channel *chan, bool offchan,
531 enum nl80211_channel_type channel_type,
532 bool channel_type_valid, unsigned int wait,
533 const u8 *buf, size_t len, bool no_cck,
534 bool dont_wait_for_ack, u64 *cookie )
535#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
536int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
537 struct ieee80211_channel *chan, bool offchan,
538 enum nl80211_channel_type channel_type,
539 bool channel_type_valid, unsigned int wait,
540 const u8 *buf, size_t len, u64 *cookie )
541#else
542int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
543 struct ieee80211_channel *chan,
544 enum nl80211_channel_type channel_type,
545 bool channel_type_valid,
546 const u8 *buf, size_t len, u64 *cookie )
547#endif //LINUX_VERSION_CODE
548{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800549#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
550 struct net_device *dev = wdev->netdev;
551#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700552 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
553 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700554 tANI_U16 extendedWait = 0;
555 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
556 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
557 tActionFrmType actionFrmType;
558 bool noack = 0;
559
Jeff Johnson295189b2012-06-20 16:38:30 -0700560#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
561 hdd_adapter_t *goAdapter;
562#endif
563
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700564#ifdef WLAN_FEATURE_P2P_DEBUG
565 if ((type == SIR_MAC_MGMT_FRAME) &&
566 (subType == SIR_MAC_MGMT_ACTION) &&
567 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
568 {
569 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800570 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700571 {
572 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
573 actionFrmType);
574 }
575 else
576 {
577 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
578 p2p_action_frame_type[actionFrmType]);
579 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
580 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
581 {
582 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
583 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800584 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700585 }
586 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
587 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
588 {
589 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
590 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
591 " completed state");
592 }
593 }
594 }
595#endif
596
Jeff Johnsone7245742012-09-05 17:12:55 -0700597#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
598 noack = dont_wait_for_ack;
599#endif
600
601 //If the wait is coming as 0 with off channel set
602 //then set the wait to 200 ms
603 if (offchan && !wait)
604 wait = ACTION_FRAME_DEFAULT_WAIT;
605
Jeff Johnson295189b2012-06-20 16:38:30 -0700606 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
607 __func__,pAdapter->device_mode);
608
609 //Call sme API to send out a action frame.
610 // OR can we send it directly through data path??
611 // After tx completion send tx status back.
612 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
613 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
614 )
615 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700616 if (type == SIR_MAC_MGMT_FRAME)
617 {
618 if (subType == SIR_MAC_MGMT_PROBE_RSP)
619 {
620 /* Drop Probe response recieved from supplicant, as for GO and
621 SAP PE itself sends probe response
622 */
623 goto err_rem_channel;
624 }
625 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
626 (subType == SIR_MAC_MGMT_DEAUTH))
627 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700628 /* During EAP failure or P2P Group Remove supplicant
629 * is sending del_station command to driver. From
630 * del_station function, Driver will send deauth frame to
631 * p2p client. No need to send disassoc frame from here.
632 * so Drop the frame here and send tx indication back to
633 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700634 */
635 tANI_U8 dstMac[ETH_ALEN] = {0};
636 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700637 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700638 "%s: Deauth/Disassoc received for STA:"
Jeff Johnsone7245742012-09-05 17:12:55 -0700639 "%02x:%02x:%02x:%02x:%02x:%02x",
640 __func__,
641 dstMac[0], dstMac[1], dstMac[2],
Jeff Johnson295189b2012-06-20 16:38:30 -0700642 dstMac[3], dstMac[4], dstMac[5]);
Jeff Johnson295189b2012-06-20 16:38:30 -0700643 goto err_rem_channel;
644 }
645 }
646 }
647
648 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800649 {
650 if ( !noack )
651 {
652 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
653 __func__);
654 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
655 }
656 else
657 {
658 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
659 __func__);
660 return -EBUSY;
661 }
662 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700663
664 hddLog( LOG1, "Action frame tx request");
665
666#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
667 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
668
669 //If GO adapter exists and operating on same frequency
670 //then we will not request remain on channel
671 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
672 == goAdapter->sessionCtx.ap.operatingChannel ) )
673 {
674 goto send_frame;
675 }
676#endif
677
678#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
679 if( offchan && wait)
680 {
681 int status;
682
683 // In case of P2P Client mode if we are already
684 // on the same channel then send the frame directly
685
686 if((cfgState->remain_on_chan_ctx != NULL) &&
687 (cfgState->current_freq == chan->center_freq)
688 )
689 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700690 hddLog(LOG1,"action frame: extending the wait time\n");
691 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700692 goto send_frame;
693 }
694
695 INIT_COMPLETION(pAdapter->offchannel_tx_event);
696
697 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
698 chan, channel_type, wait, cookie,
699 OFF_CHANNEL_ACTION_TX);
700
701 if(0 != status)
702 {
703 if( (-EBUSY == status) &&
704 (cfgState->current_freq == chan->center_freq) )
705 {
706 goto send_frame;
707 }
708 goto err_rem_channel;
709 }
710
711 /* Wait for driver to be ready on the requested channel */
712 status = wait_for_completion_interruptible_timeout(
713 &pAdapter->offchannel_tx_event,
714 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
715 if(!status)
716 {
717 hddLog( LOGE, "Not able to complete remain on channel request"
718 " within timeout period");
719 goto err_rem_channel;
720 }
721 }
722 else if ( offchan )
723 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700724 /* Check before sending action frame
725 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -0700726 if(NULL == cfgState->remain_on_chan_ctx)
727 {
728 goto err_rem_channel;
729 }
730 }
731 send_frame:
732#endif
733
Jeff Johnsone7245742012-09-05 17:12:55 -0700734 if(!noack)
735 {
736 cfgState->buf = vos_mem_malloc( len ); //buf;
737 if( cfgState->buf == NULL )
738 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -0700739
Jeff Johnsone7245742012-09-05 17:12:55 -0700740 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -0700741
Jeff Johnsone7245742012-09-05 17:12:55 -0700742 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700743
744#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700745 if( cfgState->remain_on_chan_ctx )
746 {
747 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
748 *cookie = cfgState->action_cookie;
749 }
750 else
751 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700752#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700753 *cookie = (tANI_U32) cfgState->buf;
754 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -0700755#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700756 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700757#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700758 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700759
760 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700761 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
762 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700763 )
764 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700765 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800766
Jeff Johnsone7245742012-09-05 17:12:55 -0700767 if ((type == SIR_MAC_MGMT_FRAME) &&
768 (subType == SIR_MAC_MGMT_ACTION) &&
769 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -0700770 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700771 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
772 hddLog(LOG1, "Tx Action Frame %u \n", actionFrmType);
773 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -0700774 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700775 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
776 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING \n", __func__);
777 }
778 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
779 {
780 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
781 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700782 }
783 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700784
Jeff Johnson295189b2012-06-20 16:38:30 -0700785 if (eHAL_STATUS_SUCCESS !=
786 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -0700787 sessionId, buf, len, extendedWait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -0700788 {
789 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
790 "%s: sme_sendAction returned fail", __func__);
791 goto err;
792 }
793 }
794 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
795 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
796 )
797 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700798 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700799 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700800 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700801 {
802 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
803 "%s: WLANSAP_SendAction returned fail", __func__);
804 goto err;
805 }
806 }
807
808 return 0;
809err:
Jeff Johnsone7245742012-09-05 17:12:55 -0700810 if(!noack)
811 {
812 hdd_sendActionCnf( pAdapter, FALSE );
813 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700814 return 0;
815err_rem_channel:
816 *cookie = (tANI_U32)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800817 cfg80211_mgmt_tx_status(
818#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
819 pAdapter->dev->ieee80211_ptr,
820#else
821 pAdapter->dev,
822#endif
823 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -0700824 return 0;
825}
826
827#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800828#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
829int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
830 struct wireless_dev *wdev,
831 u64 cookie)
832{
833 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
834}
835#else
836int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -0700837 struct net_device *dev,
838 u64 cookie)
839{
840 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
841}
842#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800843#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700844
845void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
846{
847 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
848
Jeff Johnsone7245742012-09-05 17:12:55 -0700849 cfgState->actionFrmState = HDD_IDLE;
850
Jeff Johnson295189b2012-06-20 16:38:30 -0700851 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
852 if( NULL == cfgState->buf )
853 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700854 return;
855 }
856
857 /* If skb is NULL it means this packet was received on CFG80211 interface
858 * else it was received on Monitor interface */
859 if( cfgState->skb == NULL )
860 {
861 /*
862 * buf is the same pointer it passed us to send. Since we are sending
863 * it through control path, we use different buffers.
864 * In case of mac80211, they just push it to the skb and pass the same
865 * data while sending tx ack status.
866 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800867 cfg80211_mgmt_tx_status(
868#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
869 pAdapter->dev->ieee80211_ptr,
870#else
871 pAdapter->dev,
872#endif
873 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700874 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
875 vos_mem_free( cfgState->buf );
876 cfgState->buf = NULL;
877 }
878 else
879 {
880 hdd_adapter_t* pMonAdapter =
881 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
882 if( pMonAdapter == NULL )
883 {
884 hddLog( LOGE, "Not able to get Monitor Adapter");
885 cfgState->skb = NULL;
886 vos_mem_free( cfgState->buf );
887 cfgState->buf = NULL;
888 complete(&pAdapter->tx_action_cnf_event);
889 return;
890 }
891 /* Send TX completion feedback over monitor interface. */
892 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
893 cfgState->skb = NULL;
894 vos_mem_free( cfgState->buf );
895 cfgState->buf = NULL;
896 /* Look for the next Mgmt packet to TX */
897 hdd_mon_tx_mgmt_pkt(pAdapter);
898 }
899 complete(&pAdapter->tx_action_cnf_event);
900}
901
902/**
903 * hdd_setP2pNoa
904 *
905 *FUNCTION:
906 * This function is called from hdd_hostapd_ioctl function when Driver
907 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
908 *
909 *LOGIC:
910 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
911 *
912 *ASSUMPTIONS:
913 *
914 *
915 *NOTE:
916 *
917 * @param dev Pointer to net device structure
918 * @param command Pointer to command
919 *
920 * @return Status
921 */
922
923int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
924{
925 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
926 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
927 VOS_STATUS status = VOS_STATUS_SUCCESS;
928 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800929 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -0700930 char *param;
931
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -0800932 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800934 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700935 param++;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800936 sscanf(param, "%d %d %d", &count, &start_time, &duration);
Jeff Johnson295189b2012-06-20 16:38:30 -0700937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
938 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d \n",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800939 __func__, count, start_time, duration);
940 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -0700941 /* PS Selection
942 * Periodic NoA (2)
943 * Single NOA (4)
944 */
945 NoA.opp_ps = 0;
946 NoA.ctWindow = 0;
947 if (count == 1)
948 {
949 NoA.duration = 0;
950 NoA.single_noa_duration = duration;
951 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
952 }
953 else
954 {
955 NoA.duration = duration;
956 NoA.single_noa_duration = 0;
957 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
958 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800959 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -0700960 NoA.count = count;
961 NoA.sessionid = pAdapter->sessionId;
962
963 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
964 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
965 "interval %d count %d single noa duration %d "
966 "PsSelection %x \n", __func__, NoA.opp_ps,
967 NoA.ctWindow, NoA.duration, NoA.interval,
968 NoA.count, NoA.single_noa_duration,
969 NoA.psSelection);
970
971 sme_p2pSetPs(hHal, &NoA);
972 return status;
973}
974
975/**
976 * hdd_setP2pOpps
977 *
978 *FUNCTION:
979 * This function is called from hdd_hostapd_ioctl function when Driver
980 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
981 *
982 *LOGIC:
983 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
984 *
985 *ASSUMPTIONS:
986 *
987 *
988 *NOTE:
989 *
990 * @param dev Pointer to net device structure
991 * @param command Pointer to command
992 *
993 * @return Status
994 */
995
996int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
997{
998 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
999 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1000 VOS_STATUS status = VOS_STATUS_SUCCESS;
1001 tP2pPsConfig NoA;
1002 char *param;
1003 int legacy_ps, opp_ps, ctwindow;
1004
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001005 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001006 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001007 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001008 param++;
1009 sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1010 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1011 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1012 __func__, legacy_ps, opp_ps, ctwindow);
1013
1014 /* PS Selection
1015 * Opportunistic Power Save (1)
1016 */
1017
1018 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1019 * When user want to set ctWindow during that time other parameters
1020 * values are coming from wpa_supplicant as -1.
1021 * Example : User want to set ctWindow with 30 then wpa_cli command :
1022 * P2P_SET ctwindow 30
1023 * Command Received at hdd_hostapd_ioctl is as below:
1024 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
1025 */
1026 if (ctwindow != -1)
1027 {
1028
1029 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1030 "Opportunistic Power Save is %s \n",
1031 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1032
1033 if (ctwindow != pAdapter->ctw)
1034 {
1035 pAdapter->ctw = ctwindow;
1036
1037 if(pAdapter->ops)
1038 {
1039 NoA.opp_ps = pAdapter->ops;
1040 NoA.ctWindow = pAdapter->ctw;
1041 NoA.duration = 0;
1042 NoA.single_noa_duration = 0;
1043 NoA.interval = 0;
1044 NoA.count = 0;
1045 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1046 NoA.sessionid = pAdapter->sessionId;
1047
1048 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1049 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1050 "interval %d count %d single noa duration %d "
1051 "PsSelection %x \n", __func__, NoA.opp_ps,
1052 NoA.ctWindow, NoA.duration, NoA.interval,
1053 NoA.count, NoA.single_noa_duration,
1054 NoA.psSelection);
1055
1056 sme_p2pSetPs(hHal, &NoA);
1057 }
1058 return 0;
1059 }
1060 }
1061
1062 if (opp_ps != -1)
1063 {
1064 pAdapter->ops = opp_ps;
1065
1066 if ((opp_ps != -1) && (pAdapter->ctw))
1067 {
1068 NoA.opp_ps = opp_ps;
1069 NoA.ctWindow = pAdapter->ctw;
1070 NoA.duration = 0;
1071 NoA.single_noa_duration = 0;
1072 NoA.interval = 0;
1073 NoA.count = 0;
1074 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1075 NoA.sessionid = pAdapter->sessionId;
1076
1077 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1078 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1079 "interval %d count %d single noa duration %d "
1080 "PsSelection %x \n", __func__, NoA.opp_ps,
1081 NoA.ctWindow, NoA.duration, NoA.interval,
1082 NoA.count, NoA.single_noa_duration,
1083 NoA.psSelection);
1084
1085 sme_p2pSetPs(hHal, &NoA);
1086 }
1087 }
1088 return status;
1089}
1090
1091int hdd_setP2pPs( struct net_device *dev, void *msgData )
1092{
1093 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1094 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1095 VOS_STATUS status = VOS_STATUS_SUCCESS;
1096 tP2pPsConfig NoA;
1097 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1098
1099 NoA.opp_ps = pappNoA->opp_ps;
1100 NoA.ctWindow = pappNoA->ctWindow;
1101 NoA.duration = pappNoA->duration;
1102 NoA.interval = pappNoA->interval;
1103 NoA.count = pappNoA->count;
1104 NoA.single_noa_duration = pappNoA->single_noa_duration;
1105 NoA.psSelection = pappNoA->psSelection;
1106 NoA.sessionid = pAdapter->sessionId;
1107
1108 sme_p2pSetPs(hHal, &NoA);
1109 return status;
1110}
1111#endif
1112
1113static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1114{
1115 tANI_U8 sessionType;
1116
1117 switch( type )
1118 {
1119 case NL80211_IFTYPE_AP:
1120 sessionType = WLAN_HDD_SOFTAP;
1121 break;
1122 case NL80211_IFTYPE_P2P_GO:
1123 sessionType = WLAN_HDD_P2P_GO;
1124 break;
1125 case NL80211_IFTYPE_P2P_CLIENT:
1126 sessionType = WLAN_HDD_P2P_CLIENT;
1127 break;
1128 case NL80211_IFTYPE_STATION:
1129 sessionType = WLAN_HDD_INFRA_STATION;
1130 break;
1131 case NL80211_IFTYPE_MONITOR:
1132 sessionType = WLAN_HDD_MONITOR;
1133 break;
1134 default:
1135 sessionType = WLAN_HDD_INFRA_STATION;
1136 break;
1137 }
1138
1139 return sessionType;
1140}
1141
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001142#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1143struct wireless_dev* wlan_hdd_add_virtual_intf(
1144 struct wiphy *wiphy, const char *name,
1145 enum nl80211_iftype type,
1146 u32 *flags, struct vif_params *params )
1147#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1148struct wireless_dev* wlan_hdd_add_virtual_intf(
1149 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1150 u32 *flags, struct vif_params *params )
1151#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001152struct net_device* wlan_hdd_add_virtual_intf(
1153 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1154 u32 *flags, struct vif_params *params )
1155#else
1156int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1157 enum nl80211_iftype type,
1158 u32 *flags, struct vif_params *params )
1159#endif
1160{
1161 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1162 hdd_adapter_t* pAdapter = NULL;
1163
1164 ENTER();
1165
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001166 if(hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
1167 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001168 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001169 "interfaces of same type are not supported currently.",__func__, type);
Jeff Johnsond13512a2012-07-17 11:42:19 -07001170 return NULL;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001171 }
1172
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001173 if (pHddCtx->isLogpInProgress)
1174 {
1175 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1176 "%s:LOGP in Progress. Ignore!!!", __func__);
1177#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1178 return NULL;
1179#else
1180 return -EAGAIN;
1181#endif
1182 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001183 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
1184 {
1185 if( (NL80211_IFTYPE_P2P_GO == type) ||
1186 (NL80211_IFTYPE_P2P_CLIENT == type) )
1187 {
1188 /* Generate the P2P Interface Address. this address must be
1189 * different from the P2P Device Address.
1190 */
1191 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1192 p2pDeviceAddress.bytes[4] ^= 0x80;
1193 pAdapter = hdd_open_adapter( pHddCtx,
1194 wlan_hdd_get_session_type(type),
1195 name, p2pDeviceAddress.bytes,
1196 VOS_TRUE );
1197 }
1198 }
1199 else
1200 {
1201 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1202 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1203 }
1204
1205 if( NULL == pAdapter)
1206 {
1207 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1208#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1209 return NULL;
1210#else
1211 return -EINVAL;
1212#endif
1213 }
1214 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001215#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1216 return pAdapter->dev->ieee80211_ptr;
1217#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001218 return pAdapter->dev;
1219#else
1220 return 0;
1221#endif
1222}
1223
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001224#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1225int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1226#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001227int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001228#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001229{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001230#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1231 struct net_device *dev = wdev->netdev;
1232#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001233 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1234 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1235 ENTER();
1236
1237 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1238 __func__,pVirtAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001239 if (pHddCtx->isLogpInProgress)
1240 {
1241 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1242 "%s:LOGP in Progress. Ignore!!!", __func__);
1243 return -EAGAIN;
1244 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001245
1246 wlan_hdd_release_intf_addr( pHddCtx,
1247 pVirtAdapter->macAddressCurrent.bytes );
1248
1249 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1250 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1251 EXIT();
1252 return 0;
1253}
1254
1255void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
1256 tANI_U32 nFrameLength, tANI_U8* pbFrames,
1257 tANI_U8 frameType )
1258{
1259 //Indicate a Frame over Monitor Intf.
1260 int rxstat;
1261 struct sk_buff *skb = NULL;
1262 int needed_headroom = 0;
1263 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1264 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001265#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001266#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1267 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1268#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001269#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001270 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1271
1272 VOS_ASSERT( (pbFrames != NULL) );
1273
1274 /* room for the radiotap header based on driver features
1275 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1276 * RX flags.
1277 * */
1278 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1279
1280 //alloc skb here
1281 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1282 if (unlikely(NULL == skb))
1283 {
1284 hddLog( LOGW, FL("Unable to allocate skb"));
1285 return;
1286 }
1287 skb_reserve(skb, VPKT_SIZE_BUFFER);
1288 if (unlikely(skb_headroom(skb) < nFrameLength))
1289 {
1290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1291 "HDD [%d]: Insufficient headroom, "
1292 "head[%p], data[%p], req[%d]",
1293 __LINE__, skb->head, skb->data, nFrameLength);
1294 kfree_skb(skb);
1295 return ;
1296 }
1297 // actually push the data
1298 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1299 /* prepend radiotap information */
1300 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1301 {
1302 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1303 //free skb
1304 kfree_skb(skb);
1305 return ;
1306 }
1307
1308 skb_reset_mac_header( skb );
1309 skb->dev = pMonAdapter->dev;
1310 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001311 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001312#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001313#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1314 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1315#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001316#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001317 rxstat = netif_rx_ni(skb);
1318 if( NET_RX_SUCCESS == rxstat )
1319 {
1320 hddLog( LOG1, FL("Success"));
1321 }
1322 else
1323 hddLog( LOGE, FL("Failed %d"), rxstat);
1324
1325 return ;
1326}
1327
1328void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
1329 tANI_U32 nFrameLength,
1330 tANI_U8* pbFrames,
1331 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301332 tANI_U32 rxChan,
1333 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001334{
1335 tANI_U16 freq;
Jeff Johnsone7245742012-09-05 17:12:55 -07001336 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001337 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001338 tActionFrmType actionFrmType;
1339 hdd_cfg80211_state_t *cfgState = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001340
1341 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d\n",
1342 __func__, frameType, nFrameLength);
1343
1344 if (NULL == pAdapter)
1345 {
1346 hddLog( LOGE, FL("pAdapter is NULL"));
1347 return;
1348 }
1349
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001350 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1351 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1352
1353 /* Get pAdapter from Destination mac address of the frame */
1354 if ((type == SIR_MAC_MGMT_FRAME) &&
1355 (subType != SIR_MAC_MGMT_PROBE_REQ))
1356 {
1357 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1358 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1359 if (NULL == pAdapter)
1360 {
1361 /* Under assumtion that we don't receive any action frame
1362 * with BCST as destination we dropping action frame
1363 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001364 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1365 MAC_ADDRESS_STR ,
1366 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1367 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
1368 " subType = %d \n",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001369 return;
1370 }
1371 }
1372
Jeff Johnson295189b2012-06-20 16:38:30 -07001373 if (NULL == pAdapter->dev)
1374 {
1375 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1376 return;
1377 }
1378
1379 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1380 {
1381 hddLog( LOGE, FL("pAdapter has invalid magic"));
1382 return;
1383 }
1384
1385 if( !nFrameLength )
1386 {
1387 hddLog( LOGE, FL("Frame Length is Invalid ZERO"));
1388 return;
1389 }
1390
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07001391 if (NULL == pbFrames) {
1392 hddLog( LOGE, FL("pbFrames is NULL"));
1393 return;
1394 }
1395
1396
Jeff Johnson295189b2012-06-20 16:38:30 -07001397 if( ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
1398 || ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1399 )
1400 {
1401 hdd_adapter_t *pMonAdapter =
1402 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1403
1404 if( NULL != pMonAdapter )
1405 {
1406 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1407 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1408 pbFrames, frameType);
1409 return;
1410 }
1411 }
1412
1413 //Channel indicated may be wrong. TODO
1414 //Indicate an action frame.
1415 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1416 {
1417 freq = ieee80211_channel_to_frequency( rxChan,
1418 IEEE80211_BAND_2GHZ);
1419 }
1420 else
1421 {
1422 freq = ieee80211_channel_to_frequency( rxChan,
1423 IEEE80211_BAND_5GHZ);
1424 }
1425
Jeff Johnsone7245742012-09-05 17:12:55 -07001426 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1427
1428 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001429 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001430 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001431 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1432 {
1433 // public action frame
1434 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001435 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 -08001436 // P2P action frames
1437 {
1438 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
1439 hddLog(LOG1, "Rx Action Frame %u \n", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001440#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001441 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1442 {
1443 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1444 actionFrmType);
1445 }
1446 else
1447 {
1448 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1449 p2p_action_frame_type[actionFrmType]);
1450 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1451 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1452 {
1453 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1454 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001455 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001456 }
1457 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1458 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1459 {
1460 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001461 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1462 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001463 }
1464 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1465 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1466 {
1467 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1468 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1469 " completed state Autonomous GO formation");
1470 }
1471 }
1472#endif
1473
1474 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
1475 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
1476 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
1477 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
1478 {
1479 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
1480 __func__);
1481 hdd_sendActionCnf(pAdapter, TRUE);
1482 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001483 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001484#ifdef WLAN_FEATURE_TDLS_DEBUG
1485 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 -07001486 {
Hoonki Leecdd8e962013-01-20 00:45:46 -08001487 wlan_hdd_tdls_set_cap(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6], 1);
1488 wlan_hdd_tdls_set_rssi(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6], rxRssi);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001489 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response <--- OTA");
1490 }
1491#endif
1492 }
1493#ifdef WLAN_FEATURE_TDLS_DEBUG
1494 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
1495 {
1496 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
1497 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
1498 {
1499 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
1500 actionFrmType);
1501 }
1502 else
1503 {
1504 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
1505 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001506 }
1507 }
1508#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07001509 }
1510
Jeff Johnson295189b2012-06-20 16:38:30 -07001511 //Indicate Frame Over Normal Interface
1512 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
1513
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001514#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1515 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
1516 pbFrames, nFrameLength,
1517 GFP_ATOMIC );
1518#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001519 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
1520 pbFrames, nFrameLength,
1521 GFP_ATOMIC );
1522#else
1523 cfg80211_rx_mgmt( pAdapter->dev, freq,
1524 pbFrames, nFrameLength,
1525 GFP_ATOMIC );
1526#endif //LINUX_VERSION_CODE
1527}
1528
1529/*
1530 * ieee80211_add_rx_radiotap_header - add radiotap header
1531 */
1532static int hdd_wlan_add_rx_radiotap_hdr (
1533 struct sk_buff *skb, int rtap_len, int flag )
1534{
1535 u8 rtap_temp[20] = {0};
1536 struct ieee80211_radiotap_header *rthdr;
1537 unsigned char *pos;
1538 u16 rx_flags = 0;
1539
1540 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
1541
1542 /* radiotap header, set always present flags */
1543 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
1544 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
1545 rthdr->it_len = cpu_to_le16(rtap_len);
1546
1547 pos = (unsigned char *) (rthdr + 1);
1548
1549 /* the order of the following fields is important */
1550
1551 /* IEEE80211_RADIOTAP_FLAGS */
1552 *pos = 0;
1553 pos++;
1554
1555 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
1556 /* ensure 2 byte alignment for the 2 byte field as required */
1557 if ((pos - (u8 *)rthdr) & 1)
1558 pos++;
1559 put_unaligned_le16(rx_flags, pos);
1560 pos += 2;
1561
1562 // actually push the data
1563 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
1564
1565 return 0;
1566}
1567
1568static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
1569 hdd_cfg80211_state_t* cfgState,
1570 tANI_BOOLEAN actionSendSuccess )
1571{
1572 struct ieee80211_radiotap_header *rthdr;
1573 unsigned char *pos;
1574 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001575#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001576#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1577 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
1578#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001579#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001580
1581 /* 2 Byte for TX flags and 1 Byte for Retry count */
1582 u32 rtHdrLen = sizeof(*rthdr) + 3;
1583
1584 u8 *data;
1585
1586 /* We have to return skb with Data starting with MAC header. We have
1587 * copied SKB data starting with MAC header to cfgState->buf. We will pull
1588 * entire skb->len from skb and then we will push cfgState->buf to skb
1589 * */
1590 if( NULL == skb_pull(skb, skb->len) )
1591 {
1592 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
1593 kfree_skb(cfgState->skb);
1594 return;
1595 }
1596
1597 data = skb_push( skb, cfgState->len );
1598
1599 if (data == NULL)
1600 {
1601 hddLog( LOGE, FL("Not Able to Push %d byte to skb"), cfgState->len);
1602 kfree_skb( cfgState->skb );
1603 return;
1604 }
1605
1606 memcpy( data, cfgState->buf, cfgState->len );
1607
1608 /* send frame to monitor interfaces now */
1609 if( skb_headroom(skb) < rtHdrLen )
1610 {
1611 hddLog( LOGE, FL("No headroom for rtap header"));
1612 kfree_skb(cfgState->skb);
1613 return;
1614 }
1615
1616 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
1617
1618 memset( rthdr, 0, rtHdrLen );
1619 rthdr->it_len = cpu_to_le16( rtHdrLen );
1620 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
1621 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
1622 );
1623
1624 pos = (unsigned char *)( rthdr+1 );
1625
1626 // Fill TX flags
1627 *pos = actionSendSuccess;
1628 pos += 2;
1629
1630 // Fill retry count
1631 *pos = 0;
1632 pos++;
1633
1634 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001635 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001636 skb->pkt_type = PACKET_OTHERHOST;
1637 skb->protocol = htons(ETH_P_802_2);
1638 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001639#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001640#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1641 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1642#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001643#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001644 if (in_interrupt())
1645 netif_rx( skb );
1646 else
1647 netif_rx_ni( skb );
1648
1649 /* Enable Queues which we have disabled earlier */
1650 netif_tx_start_all_queues( pAdapter->dev );
1651
1652}
1653#endif // CONFIG_CFG80211