blob: 29fb905f17dd58004344fdfde449ee169cbfa602 [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
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800564 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
565 {
566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
567 "%s:LOGP in Progress. Ignore!!!", __func__);
568 return -EBUSY;
569 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700570#ifdef WLAN_FEATURE_P2P_DEBUG
571 if ((type == SIR_MAC_MGMT_FRAME) &&
572 (subType == SIR_MAC_MGMT_ACTION) &&
573 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
574 {
575 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800576 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700577 {
578 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
579 actionFrmType);
580 }
581 else
582 {
583 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
584 p2p_action_frame_type[actionFrmType]);
585 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
586 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
587 {
588 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
589 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800590 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700591 }
592 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
593 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
594 {
595 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
596 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
597 " completed state");
598 }
599 }
600 }
601#endif
602
Jeff Johnsone7245742012-09-05 17:12:55 -0700603#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
604 noack = dont_wait_for_ack;
605#endif
606
607 //If the wait is coming as 0 with off channel set
608 //then set the wait to 200 ms
609 if (offchan && !wait)
610 wait = ACTION_FRAME_DEFAULT_WAIT;
611
Jeff Johnson295189b2012-06-20 16:38:30 -0700612 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
613 __func__,pAdapter->device_mode);
614
615 //Call sme API to send out a action frame.
616 // OR can we send it directly through data path??
617 // After tx completion send tx status back.
618 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
619 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
620 )
621 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 if (type == SIR_MAC_MGMT_FRAME)
623 {
624 if (subType == SIR_MAC_MGMT_PROBE_RSP)
625 {
626 /* Drop Probe response recieved from supplicant, as for GO and
627 SAP PE itself sends probe response
628 */
629 goto err_rem_channel;
630 }
631 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
632 (subType == SIR_MAC_MGMT_DEAUTH))
633 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700634 /* During EAP failure or P2P Group Remove supplicant
635 * is sending del_station command to driver. From
636 * del_station function, Driver will send deauth frame to
637 * p2p client. No need to send disassoc frame from here.
638 * so Drop the frame here and send tx indication back to
639 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700640 */
641 tANI_U8 dstMac[ETH_ALEN] = {0};
642 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700643 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700644 "%s: Deauth/Disassoc received for STA:"
Jeff Johnsone7245742012-09-05 17:12:55 -0700645 "%02x:%02x:%02x:%02x:%02x:%02x",
646 __func__,
647 dstMac[0], dstMac[1], dstMac[2],
Jeff Johnson295189b2012-06-20 16:38:30 -0700648 dstMac[3], dstMac[4], dstMac[5]);
Jeff Johnson295189b2012-06-20 16:38:30 -0700649 goto err_rem_channel;
650 }
651 }
652 }
653
654 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800655 {
656 if ( !noack )
657 {
658 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
659 __func__);
660 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
661 }
662 else
663 {
664 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
665 __func__);
666 return -EBUSY;
667 }
668 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700669
670 hddLog( LOG1, "Action frame tx request");
671
672#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
673 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
674
675 //If GO adapter exists and operating on same frequency
676 //then we will not request remain on channel
677 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
678 == goAdapter->sessionCtx.ap.operatingChannel ) )
679 {
680 goto send_frame;
681 }
682#endif
683
684#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
685 if( offchan && wait)
686 {
687 int status;
688
689 // In case of P2P Client mode if we are already
690 // on the same channel then send the frame directly
691
692 if((cfgState->remain_on_chan_ctx != NULL) &&
693 (cfgState->current_freq == chan->center_freq)
694 )
695 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700696 hddLog(LOG1,"action frame: extending the wait time\n");
697 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700698 goto send_frame;
699 }
700
701 INIT_COMPLETION(pAdapter->offchannel_tx_event);
702
703 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
704 chan, channel_type, wait, cookie,
705 OFF_CHANNEL_ACTION_TX);
706
707 if(0 != status)
708 {
709 if( (-EBUSY == status) &&
710 (cfgState->current_freq == chan->center_freq) )
711 {
712 goto send_frame;
713 }
714 goto err_rem_channel;
715 }
716
717 /* Wait for driver to be ready on the requested channel */
718 status = wait_for_completion_interruptible_timeout(
719 &pAdapter->offchannel_tx_event,
720 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
721 if(!status)
722 {
723 hddLog( LOGE, "Not able to complete remain on channel request"
724 " within timeout period");
725 goto err_rem_channel;
726 }
727 }
728 else if ( offchan )
729 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700730 /* Check before sending action frame
731 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -0700732 if(NULL == cfgState->remain_on_chan_ctx)
733 {
734 goto err_rem_channel;
735 }
736 }
737 send_frame:
738#endif
739
Jeff Johnsone7245742012-09-05 17:12:55 -0700740 if(!noack)
741 {
742 cfgState->buf = vos_mem_malloc( len ); //buf;
743 if( cfgState->buf == NULL )
744 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -0700745
Jeff Johnsone7245742012-09-05 17:12:55 -0700746 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -0700747
Jeff Johnsone7245742012-09-05 17:12:55 -0700748 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700749
750#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700751 if( cfgState->remain_on_chan_ctx )
752 {
753 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
754 *cookie = cfgState->action_cookie;
755 }
756 else
757 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700758#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700759 *cookie = (tANI_U32) cfgState->buf;
760 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -0700761#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700762 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700763#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700764 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700765
766 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700767 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
768 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700769 )
770 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700771 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800772
Jeff Johnsone7245742012-09-05 17:12:55 -0700773 if ((type == SIR_MAC_MGMT_FRAME) &&
774 (subType == SIR_MAC_MGMT_ACTION) &&
775 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -0700776 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700777 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
778 hddLog(LOG1, "Tx Action Frame %u \n", actionFrmType);
779 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -0700780 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700781 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
782 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING \n", __func__);
783 }
784 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
785 {
786 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
787 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700788 }
789 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700790
Jeff Johnson295189b2012-06-20 16:38:30 -0700791 if (eHAL_STATUS_SUCCESS !=
792 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -0700793 sessionId, buf, len, extendedWait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -0700794 {
795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
796 "%s: sme_sendAction returned fail", __func__);
797 goto err;
798 }
799 }
800 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
801 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
802 )
803 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700804 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700805 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700806 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700807 {
808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
809 "%s: WLANSAP_SendAction returned fail", __func__);
810 goto err;
811 }
812 }
813
814 return 0;
815err:
Jeff Johnsone7245742012-09-05 17:12:55 -0700816 if(!noack)
817 {
818 hdd_sendActionCnf( pAdapter, FALSE );
819 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700820 return 0;
821err_rem_channel:
822 *cookie = (tANI_U32)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800823 cfg80211_mgmt_tx_status(
824#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
825 pAdapter->dev->ieee80211_ptr,
826#else
827 pAdapter->dev,
828#endif
829 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -0700830 return 0;
831}
832
833#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800834#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
835int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
836 struct wireless_dev *wdev,
837 u64 cookie)
838{
839 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
840}
841#else
842int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -0700843 struct net_device *dev,
844 u64 cookie)
845{
846 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
847}
848#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800849#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700850
851void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
852{
853 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
854
Jeff Johnsone7245742012-09-05 17:12:55 -0700855 cfgState->actionFrmState = HDD_IDLE;
856
Jeff Johnson295189b2012-06-20 16:38:30 -0700857 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
858 if( NULL == cfgState->buf )
859 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700860 return;
861 }
862
863 /* If skb is NULL it means this packet was received on CFG80211 interface
864 * else it was received on Monitor interface */
865 if( cfgState->skb == NULL )
866 {
867 /*
868 * buf is the same pointer it passed us to send. Since we are sending
869 * it through control path, we use different buffers.
870 * In case of mac80211, they just push it to the skb and pass the same
871 * data while sending tx ack status.
872 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800873 cfg80211_mgmt_tx_status(
874#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
875 pAdapter->dev->ieee80211_ptr,
876#else
877 pAdapter->dev,
878#endif
879 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700880 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
881 vos_mem_free( cfgState->buf );
882 cfgState->buf = NULL;
883 }
884 else
885 {
886 hdd_adapter_t* pMonAdapter =
887 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
888 if( pMonAdapter == NULL )
889 {
890 hddLog( LOGE, "Not able to get Monitor Adapter");
891 cfgState->skb = NULL;
892 vos_mem_free( cfgState->buf );
893 cfgState->buf = NULL;
894 complete(&pAdapter->tx_action_cnf_event);
895 return;
896 }
897 /* Send TX completion feedback over monitor interface. */
898 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
899 cfgState->skb = NULL;
900 vos_mem_free( cfgState->buf );
901 cfgState->buf = NULL;
902 /* Look for the next Mgmt packet to TX */
903 hdd_mon_tx_mgmt_pkt(pAdapter);
904 }
905 complete(&pAdapter->tx_action_cnf_event);
906}
907
908/**
909 * hdd_setP2pNoa
910 *
911 *FUNCTION:
912 * This function is called from hdd_hostapd_ioctl function when Driver
913 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
914 *
915 *LOGIC:
916 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
917 *
918 *ASSUMPTIONS:
919 *
920 *
921 *NOTE:
922 *
923 * @param dev Pointer to net device structure
924 * @param command Pointer to command
925 *
926 * @return Status
927 */
928
929int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
930{
931 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
932 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
933 VOS_STATUS status = VOS_STATUS_SUCCESS;
934 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800935 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -0700936 char *param;
937
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -0800938 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -0700939 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800940 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700941 param++;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800942 sscanf(param, "%d %d %d", &count, &start_time, &duration);
Jeff Johnson295189b2012-06-20 16:38:30 -0700943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
944 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d \n",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800945 __func__, count, start_time, duration);
946 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -0700947 /* PS Selection
948 * Periodic NoA (2)
949 * Single NOA (4)
950 */
951 NoA.opp_ps = 0;
952 NoA.ctWindow = 0;
953 if (count == 1)
954 {
955 NoA.duration = 0;
956 NoA.single_noa_duration = duration;
957 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
958 }
959 else
960 {
961 NoA.duration = duration;
962 NoA.single_noa_duration = 0;
963 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
964 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800965 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -0700966 NoA.count = count;
967 NoA.sessionid = pAdapter->sessionId;
968
969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
970 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
971 "interval %d count %d single noa duration %d "
972 "PsSelection %x \n", __func__, NoA.opp_ps,
973 NoA.ctWindow, NoA.duration, NoA.interval,
974 NoA.count, NoA.single_noa_duration,
975 NoA.psSelection);
976
977 sme_p2pSetPs(hHal, &NoA);
978 return status;
979}
980
981/**
982 * hdd_setP2pOpps
983 *
984 *FUNCTION:
985 * This function is called from hdd_hostapd_ioctl function when Driver
986 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
987 *
988 *LOGIC:
989 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
990 *
991 *ASSUMPTIONS:
992 *
993 *
994 *NOTE:
995 *
996 * @param dev Pointer to net device structure
997 * @param command Pointer to command
998 *
999 * @return Status
1000 */
1001
1002int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1003{
1004 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1005 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1006 VOS_STATUS status = VOS_STATUS_SUCCESS;
1007 tP2pPsConfig NoA;
1008 char *param;
1009 int legacy_ps, opp_ps, ctwindow;
1010
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001011 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001012 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001013 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001014 param++;
1015 sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1016 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1017 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1018 __func__, legacy_ps, opp_ps, ctwindow);
1019
1020 /* PS Selection
1021 * Opportunistic Power Save (1)
1022 */
1023
1024 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1025 * When user want to set ctWindow during that time other parameters
1026 * values are coming from wpa_supplicant as -1.
1027 * Example : User want to set ctWindow with 30 then wpa_cli command :
1028 * P2P_SET ctwindow 30
1029 * Command Received at hdd_hostapd_ioctl is as below:
1030 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
1031 */
1032 if (ctwindow != -1)
1033 {
1034
1035 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1036 "Opportunistic Power Save is %s \n",
1037 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1038
1039 if (ctwindow != pAdapter->ctw)
1040 {
1041 pAdapter->ctw = ctwindow;
1042
1043 if(pAdapter->ops)
1044 {
1045 NoA.opp_ps = pAdapter->ops;
1046 NoA.ctWindow = pAdapter->ctw;
1047 NoA.duration = 0;
1048 NoA.single_noa_duration = 0;
1049 NoA.interval = 0;
1050 NoA.count = 0;
1051 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1052 NoA.sessionid = pAdapter->sessionId;
1053
1054 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1055 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1056 "interval %d count %d single noa duration %d "
1057 "PsSelection %x \n", __func__, NoA.opp_ps,
1058 NoA.ctWindow, NoA.duration, NoA.interval,
1059 NoA.count, NoA.single_noa_duration,
1060 NoA.psSelection);
1061
1062 sme_p2pSetPs(hHal, &NoA);
1063 }
1064 return 0;
1065 }
1066 }
1067
1068 if (opp_ps != -1)
1069 {
1070 pAdapter->ops = opp_ps;
1071
1072 if ((opp_ps != -1) && (pAdapter->ctw))
1073 {
1074 NoA.opp_ps = opp_ps;
1075 NoA.ctWindow = pAdapter->ctw;
1076 NoA.duration = 0;
1077 NoA.single_noa_duration = 0;
1078 NoA.interval = 0;
1079 NoA.count = 0;
1080 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1081 NoA.sessionid = pAdapter->sessionId;
1082
1083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1084 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1085 "interval %d count %d single noa duration %d "
1086 "PsSelection %x \n", __func__, NoA.opp_ps,
1087 NoA.ctWindow, NoA.duration, NoA.interval,
1088 NoA.count, NoA.single_noa_duration,
1089 NoA.psSelection);
1090
1091 sme_p2pSetPs(hHal, &NoA);
1092 }
1093 }
1094 return status;
1095}
1096
1097int hdd_setP2pPs( struct net_device *dev, void *msgData )
1098{
1099 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1100 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1101 VOS_STATUS status = VOS_STATUS_SUCCESS;
1102 tP2pPsConfig NoA;
1103 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1104
1105 NoA.opp_ps = pappNoA->opp_ps;
1106 NoA.ctWindow = pappNoA->ctWindow;
1107 NoA.duration = pappNoA->duration;
1108 NoA.interval = pappNoA->interval;
1109 NoA.count = pappNoA->count;
1110 NoA.single_noa_duration = pappNoA->single_noa_duration;
1111 NoA.psSelection = pappNoA->psSelection;
1112 NoA.sessionid = pAdapter->sessionId;
1113
1114 sme_p2pSetPs(hHal, &NoA);
1115 return status;
1116}
1117#endif
1118
1119static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1120{
1121 tANI_U8 sessionType;
1122
1123 switch( type )
1124 {
1125 case NL80211_IFTYPE_AP:
1126 sessionType = WLAN_HDD_SOFTAP;
1127 break;
1128 case NL80211_IFTYPE_P2P_GO:
1129 sessionType = WLAN_HDD_P2P_GO;
1130 break;
1131 case NL80211_IFTYPE_P2P_CLIENT:
1132 sessionType = WLAN_HDD_P2P_CLIENT;
1133 break;
1134 case NL80211_IFTYPE_STATION:
1135 sessionType = WLAN_HDD_INFRA_STATION;
1136 break;
1137 case NL80211_IFTYPE_MONITOR:
1138 sessionType = WLAN_HDD_MONITOR;
1139 break;
1140 default:
1141 sessionType = WLAN_HDD_INFRA_STATION;
1142 break;
1143 }
1144
1145 return sessionType;
1146}
1147
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001148#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1149struct wireless_dev* wlan_hdd_add_virtual_intf(
1150 struct wiphy *wiphy, const char *name,
1151 enum nl80211_iftype type,
1152 u32 *flags, struct vif_params *params )
1153#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1154struct wireless_dev* wlan_hdd_add_virtual_intf(
1155 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1156 u32 *flags, struct vif_params *params )
1157#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001158struct net_device* wlan_hdd_add_virtual_intf(
1159 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1160 u32 *flags, struct vif_params *params )
1161#else
1162int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1163 enum nl80211_iftype type,
1164 u32 *flags, struct vif_params *params )
1165#endif
1166{
1167 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1168 hdd_adapter_t* pAdapter = NULL;
1169
1170 ENTER();
1171
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001172 if(hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
1173 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001174 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001175 "interfaces of same type are not supported currently.",__func__, type);
Jeff Johnsond13512a2012-07-17 11:42:19 -07001176 return NULL;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001177 }
1178
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001179 if (pHddCtx->isLogpInProgress)
1180 {
1181 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1182 "%s:LOGP in Progress. Ignore!!!", __func__);
1183#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1184 return NULL;
1185#else
1186 return -EAGAIN;
1187#endif
1188 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001189 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
1190 {
1191 if( (NL80211_IFTYPE_P2P_GO == type) ||
1192 (NL80211_IFTYPE_P2P_CLIENT == type) )
1193 {
1194 /* Generate the P2P Interface Address. this address must be
1195 * different from the P2P Device Address.
1196 */
1197 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1198 p2pDeviceAddress.bytes[4] ^= 0x80;
1199 pAdapter = hdd_open_adapter( pHddCtx,
1200 wlan_hdd_get_session_type(type),
1201 name, p2pDeviceAddress.bytes,
1202 VOS_TRUE );
1203 }
1204 }
1205 else
1206 {
1207 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1208 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1209 }
1210
1211 if( NULL == pAdapter)
1212 {
1213 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1214#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1215 return NULL;
1216#else
1217 return -EINVAL;
1218#endif
1219 }
1220 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001221#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1222 return pAdapter->dev->ieee80211_ptr;
1223#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001224 return pAdapter->dev;
1225#else
1226 return 0;
1227#endif
1228}
1229
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001230#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1231int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1232#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001233int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001234#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001235{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001236#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1237 struct net_device *dev = wdev->netdev;
1238#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001239 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1240 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1241 ENTER();
1242
1243 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1244 __func__,pVirtAdapter->device_mode);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001245 if (pHddCtx->isLogpInProgress)
1246 {
1247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1248 "%s:LOGP in Progress. Ignore!!!", __func__);
1249 return -EAGAIN;
1250 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001251
1252 wlan_hdd_release_intf_addr( pHddCtx,
1253 pVirtAdapter->macAddressCurrent.bytes );
1254
1255 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1256 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1257 EXIT();
1258 return 0;
1259}
1260
1261void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
1262 tANI_U32 nFrameLength, tANI_U8* pbFrames,
1263 tANI_U8 frameType )
1264{
1265 //Indicate a Frame over Monitor Intf.
1266 int rxstat;
1267 struct sk_buff *skb = NULL;
1268 int needed_headroom = 0;
1269 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1270 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001271#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001272#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1273 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1274#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001275#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1277
1278 VOS_ASSERT( (pbFrames != NULL) );
1279
1280 /* room for the radiotap header based on driver features
1281 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1282 * RX flags.
1283 * */
1284 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1285
1286 //alloc skb here
1287 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1288 if (unlikely(NULL == skb))
1289 {
1290 hddLog( LOGW, FL("Unable to allocate skb"));
1291 return;
1292 }
1293 skb_reserve(skb, VPKT_SIZE_BUFFER);
1294 if (unlikely(skb_headroom(skb) < nFrameLength))
1295 {
1296 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1297 "HDD [%d]: Insufficient headroom, "
1298 "head[%p], data[%p], req[%d]",
1299 __LINE__, skb->head, skb->data, nFrameLength);
1300 kfree_skb(skb);
1301 return ;
1302 }
1303 // actually push the data
1304 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1305 /* prepend radiotap information */
1306 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1307 {
1308 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1309 //free skb
1310 kfree_skb(skb);
1311 return ;
1312 }
1313
1314 skb_reset_mac_header( skb );
1315 skb->dev = pMonAdapter->dev;
1316 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001317 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001318#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001319#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1320 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1321#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001322#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001323 rxstat = netif_rx_ni(skb);
1324 if( NET_RX_SUCCESS == rxstat )
1325 {
1326 hddLog( LOG1, FL("Success"));
1327 }
1328 else
1329 hddLog( LOGE, FL("Failed %d"), rxstat);
1330
1331 return ;
1332}
1333
1334void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
1335 tANI_U32 nFrameLength,
1336 tANI_U8* pbFrames,
1337 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301338 tANI_U32 rxChan,
1339 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001340{
1341 tANI_U16 freq;
Jeff Johnsone7245742012-09-05 17:12:55 -07001342 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001343 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001344 tActionFrmType actionFrmType;
1345 hdd_cfg80211_state_t *cfgState = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001346
1347 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d\n",
1348 __func__, frameType, nFrameLength);
1349
1350 if (NULL == pAdapter)
1351 {
1352 hddLog( LOGE, FL("pAdapter is NULL"));
1353 return;
1354 }
1355
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001356 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1357 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1358
1359 /* Get pAdapter from Destination mac address of the frame */
1360 if ((type == SIR_MAC_MGMT_FRAME) &&
1361 (subType != SIR_MAC_MGMT_PROBE_REQ))
1362 {
1363 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1364 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1365 if (NULL == pAdapter)
1366 {
1367 /* Under assumtion that we don't receive any action frame
1368 * with BCST as destination we dropping action frame
1369 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001370 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1371 MAC_ADDRESS_STR ,
1372 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1373 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
1374 " subType = %d \n",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001375 return;
1376 }
1377 }
1378
Jeff Johnson295189b2012-06-20 16:38:30 -07001379 if (NULL == pAdapter->dev)
1380 {
1381 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1382 return;
1383 }
1384
1385 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1386 {
1387 hddLog( LOGE, FL("pAdapter has invalid magic"));
1388 return;
1389 }
1390
1391 if( !nFrameLength )
1392 {
1393 hddLog( LOGE, FL("Frame Length is Invalid ZERO"));
1394 return;
1395 }
1396
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07001397 if (NULL == pbFrames) {
1398 hddLog( LOGE, FL("pbFrames is NULL"));
1399 return;
1400 }
1401
1402
Jeff Johnson295189b2012-06-20 16:38:30 -07001403 if( ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
1404 || ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1405 )
1406 {
1407 hdd_adapter_t *pMonAdapter =
1408 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1409
1410 if( NULL != pMonAdapter )
1411 {
1412 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1413 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1414 pbFrames, frameType);
1415 return;
1416 }
1417 }
1418
1419 //Channel indicated may be wrong. TODO
1420 //Indicate an action frame.
1421 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1422 {
1423 freq = ieee80211_channel_to_frequency( rxChan,
1424 IEEE80211_BAND_2GHZ);
1425 }
1426 else
1427 {
1428 freq = ieee80211_channel_to_frequency( rxChan,
1429 IEEE80211_BAND_5GHZ);
1430 }
1431
Jeff Johnsone7245742012-09-05 17:12:55 -07001432 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1433
1434 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001435 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001436 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001437 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1438 {
1439 // public action frame
1440 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001441 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 -08001442 // P2P action frames
1443 {
1444 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
1445 hddLog(LOG1, "Rx Action Frame %u \n", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001446#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001447 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1448 {
1449 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1450 actionFrmType);
1451 }
1452 else
1453 {
1454 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1455 p2p_action_frame_type[actionFrmType]);
1456 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1457 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1458 {
1459 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1460 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001461 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001462 }
1463 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1464 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1465 {
1466 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001467 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1468 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001469 }
1470 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1471 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1472 {
1473 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1474 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1475 " completed state Autonomous GO formation");
1476 }
1477 }
1478#endif
1479
1480 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
1481 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
1482 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
1483 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
1484 {
1485 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
1486 __func__);
1487 hdd_sendActionCnf(pAdapter, TRUE);
1488 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001489 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001490#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001491 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 -07001492 {
Hoonki Leecdd8e962013-01-20 00:45:46 -08001493 wlan_hdd_tdls_set_cap(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6], 1);
1494 wlan_hdd_tdls_set_rssi(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6], rxRssi);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001495 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response <--- OTA");
1496 }
1497#endif
1498 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001499#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001500 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
1501 {
1502 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
1503 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
1504 {
1505 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
1506 actionFrmType);
1507 }
1508 else
1509 {
1510 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
1511 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001512 }
1513 }
1514#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07001515 }
1516
Jeff Johnson295189b2012-06-20 16:38:30 -07001517 //Indicate Frame Over Normal Interface
1518 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
1519
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001520#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1521 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
1522 pbFrames, nFrameLength,
1523 GFP_ATOMIC );
1524#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001525 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
1526 pbFrames, nFrameLength,
1527 GFP_ATOMIC );
1528#else
1529 cfg80211_rx_mgmt( pAdapter->dev, freq,
1530 pbFrames, nFrameLength,
1531 GFP_ATOMIC );
1532#endif //LINUX_VERSION_CODE
1533}
1534
1535/*
1536 * ieee80211_add_rx_radiotap_header - add radiotap header
1537 */
1538static int hdd_wlan_add_rx_radiotap_hdr (
1539 struct sk_buff *skb, int rtap_len, int flag )
1540{
1541 u8 rtap_temp[20] = {0};
1542 struct ieee80211_radiotap_header *rthdr;
1543 unsigned char *pos;
1544 u16 rx_flags = 0;
1545
1546 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
1547
1548 /* radiotap header, set always present flags */
1549 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
1550 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
1551 rthdr->it_len = cpu_to_le16(rtap_len);
1552
1553 pos = (unsigned char *) (rthdr + 1);
1554
1555 /* the order of the following fields is important */
1556
1557 /* IEEE80211_RADIOTAP_FLAGS */
1558 *pos = 0;
1559 pos++;
1560
1561 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
1562 /* ensure 2 byte alignment for the 2 byte field as required */
1563 if ((pos - (u8 *)rthdr) & 1)
1564 pos++;
1565 put_unaligned_le16(rx_flags, pos);
1566 pos += 2;
1567
1568 // actually push the data
1569 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
1570
1571 return 0;
1572}
1573
1574static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
1575 hdd_cfg80211_state_t* cfgState,
1576 tANI_BOOLEAN actionSendSuccess )
1577{
1578 struct ieee80211_radiotap_header *rthdr;
1579 unsigned char *pos;
1580 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001581#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001582#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1583 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
1584#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001585#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001586
1587 /* 2 Byte for TX flags and 1 Byte for Retry count */
1588 u32 rtHdrLen = sizeof(*rthdr) + 3;
1589
1590 u8 *data;
1591
1592 /* We have to return skb with Data starting with MAC header. We have
1593 * copied SKB data starting with MAC header to cfgState->buf. We will pull
1594 * entire skb->len from skb and then we will push cfgState->buf to skb
1595 * */
1596 if( NULL == skb_pull(skb, skb->len) )
1597 {
1598 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
1599 kfree_skb(cfgState->skb);
1600 return;
1601 }
1602
1603 data = skb_push( skb, cfgState->len );
1604
1605 if (data == NULL)
1606 {
1607 hddLog( LOGE, FL("Not Able to Push %d byte to skb"), cfgState->len);
1608 kfree_skb( cfgState->skb );
1609 return;
1610 }
1611
1612 memcpy( data, cfgState->buf, cfgState->len );
1613
1614 /* send frame to monitor interfaces now */
1615 if( skb_headroom(skb) < rtHdrLen )
1616 {
1617 hddLog( LOGE, FL("No headroom for rtap header"));
1618 kfree_skb(cfgState->skb);
1619 return;
1620 }
1621
1622 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
1623
1624 memset( rthdr, 0, rtHdrLen );
1625 rthdr->it_len = cpu_to_le16( rtHdrLen );
1626 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
1627 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
1628 );
1629
1630 pos = (unsigned char *)( rthdr+1 );
1631
1632 // Fill TX flags
1633 *pos = actionSendSuccess;
1634 pos += 2;
1635
1636 // Fill retry count
1637 *pos = 0;
1638 pos++;
1639
1640 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001641 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001642 skb->pkt_type = PACKET_OTHERHOST;
1643 skb->protocol = htons(ETH_P_802_2);
1644 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001645#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001646#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1647 wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION);
1648#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001649#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001650 if (in_interrupt())
1651 netif_rx( skb );
1652 else
1653 netif_rx_ni( skb );
1654
1655 /* Enable Queues which we have disabled earlier */
1656 netif_tx_start_all_queues( pAdapter->dev );
1657
1658}
1659#endif // CONFIG_CFG80211