blob: dc07ac750a7d2a3452f4c32f0fa271de9cba83bf [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/**========================================================================
43
44 \file wlan_hdd_p2p.c
45
46 \brief WLAN Host Device Driver implementation for P2P commands interface
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070053
54#include <wlan_hdd_includes.h>
55#include <wlan_hdd_hostapd.h>
56#include <net/cfg80211.h>
57#include "sme_Api.h"
58#include "wlan_hdd_p2p.h"
59#include "sapApi.h"
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053060#include "wlan_hdd_main.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070061
62#include <linux/netdevice.h>
63#include <linux/skbuff.h>
64#include <linux/etherdevice.h>
65#include <net/ieee80211_radiotap.h>
Hoonki Lee1090c6a2013-01-16 17:40:54 -080066#ifdef FEATURE_WLAN_TDLS
67#include "wlan_hdd_tdls.h"
68#endif
Jeff Johnson295189b2012-06-20 16:38:30 -070069
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080070//Ms to Micro Sec
71#define MS_TO_MUS(x) ((x)*1000);
72
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070073#ifdef WLAN_FEATURE_P2P_DEBUG
74#define MAX_P2P_ACTION_FRAME_TYPE 9
75const char *p2p_action_frame_type[]={"GO Negotiation Request",
76 "GO Negotiation Response",
77 "GO Negotiation Confirmation",
78 "P2P Invitation Request",
79 "P2P Invitation Response",
80 "Device Discoverability Request",
81 "Device Discoverability Response",
82 "Provision Discovery Request",
83 "Provision Discovery Response"};
84
85/* We no need to protect this variable since
86 * there is no chance of race to condition
87 * and also not make any complicating the code
88 * just for debugging log
89 */
90tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
91
92#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -080093#ifdef WLAN_FEATURE_TDLS_DEBUG
94#define MAX_TDLS_ACTION_FRAME_TYPE 11
95const char *tdls_action_frame_type[] = {"TDLS Setup Request",
96 "TDLS Setup Response",
97 "TDLS Setup Confirm",
98 "TDLS Teardown",
99 "TDLS Peer Traffic Indication",
100 "TDLS Channel Switch Request",
101 "TDLS Channel Switch Response",
102 "TDLS Peer PSM Request",
103 "TDLS Peer PSM Response",
104 "TDLS Peer Traffic Response",
105 "TDLS Discovery Request" };
106#endif
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700107
Jeff Johnson295189b2012-06-20 16:38:30 -0700108extern struct net_device_ops net_ops_struct;
109
110static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
111 int rtap_len, int flag );
112
113static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
114 hdd_cfg80211_state_t* cfgState,
115 tANI_BOOLEAN actionSendSuccess );
116
117static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
118 tANI_U32 nFrameLength,
119 tANI_U8* pbFrames,
120 tANI_U8 frameType );
vamsi9bd92b72013-12-26 14:11:29 +0530121
122static v_BOOL_t hdd_p2p_is_action_type_rsp( const u8 *buf )
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530123{
vamsi9bd92b72013-12-26 14:11:29 +0530124 tActionFrmType actionFrmType;
125 const u8 *ouiPtr;
126
127 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
128 WLAN_HDD_PUBLIC_ACTION_FRAME ) {
129 return VOS_FALSE;
130 }
131
132 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] !=
133 WLAN_HDD_VENDOR_SPECIFIC_ACTION ) {
134 return VOS_FALSE;
135 }
136
137 ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET];
138
139 if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) {
140 return VOS_FALSE;
141 }
142
143 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] !=
144 WLAN_HDD_WFA_P2P_OUI_TYPE ) {
145 return VOS_FALSE;
146 }
147
148 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
149 if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
150 actionFrmType != WLAN_HDD_GO_NEG_REQ &&
151 actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
152 actionFrmType != WLAN_HDD_PROV_DIS_REQ )
153 return VOS_TRUE;
154 else
155 return VOS_FALSE;
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530156}
Jeff Johnson295189b2012-06-20 16:38:30 -0700157
Jeff Johnson295189b2012-06-20 16:38:30 -0700158eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
159 eHalStatus status )
160{
161 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700162 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
163 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
164
165 if( pRemainChanCtx == NULL )
166 {
167 hddLog( LOGW,
168 "%s: No Rem on channel pending for which Rsp is received", __func__);
169 return eHAL_STATUS_SUCCESS;
170 }
171
172 hddLog( LOG1, "Received remain on channel rsp");
173
174 cfgState->remain_on_chan_ctx = NULL;
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530175 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request &&
176 !pAdapter->internalCancelRemainOnChReq )
Jeff Johnson295189b2012-06-20 16:38:30 -0700177 {
178 if( cfgState->buf )
179 {
180 hddLog( LOGP,
181 "%s: We need to receive yet an ack from one of tx packet",
182 __func__);
183 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800184 cfg80211_remain_on_channel_expired(
185#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
186 pRemainChanCtx->dev->ieee80211_ptr,
187#else
188 pRemainChanCtx->dev,
189#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700190 pRemainChanCtx->cookie,
191 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700192#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
193 pRemainChanCtx->chan_type,
194#endif
195 GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -0700196 }
197
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530198 pAdapter->internalCancelRemainOnChReq = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700199
200 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700201 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
202 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700203 )
204 {
205 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800206 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
207 {
208 sme_DeregisterMgmtFrame(
209 hHal, sessionId,
210 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
211 NULL, 0 );
212 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700213 }
214 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
215 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
216 )
217 {
218 WLANSAP_DeRegisterMgmtFrame(
219 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
220 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
221 NULL, 0 );
222 }
223
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800224 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800225 pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700226 complete(&pAdapter->cancel_rem_on_chan_var);
227 return eHAL_STATUS_SUCCESS;
228}
229
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -0800230void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700231{
Jeff Johnson295189b2012-06-20 16:38:30 -0700232 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
233 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700234
Jeff Johnson32d95a32012-09-10 13:15:23 -0700235 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700236 {
Jeff Johnson32d95a32012-09-10 13:15:23 -0700237 hddLog( LOG1, "Cancel Existing Remain on Channel");
238
239 /* Wait till remain on channel ready indication before issuing cancel
240 * remain on channel request, otherwise if remain on channel not
241 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700242 * will be in unknown state.
243 */
244 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
245 msecs_to_jiffies(WAIT_REM_CHAN_READY));
c_hpothu7f63e882013-10-02 19:13:35 +0530246 if (0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -0700247 {
248 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530249 "%s: timeout waiting for remain on channel ready indication %d",
250 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 }
252
253 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700254
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 /* Issue abort remain on chan request to sme.
256 * The remain on channel callback will make sure the remain_on_chan
257 * expired event is sent.
258 */
259 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700260 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
261 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 )
263 {
264 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
265 pAdapter->sessionId );
266 }
267 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
268 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
269 )
270 {
271 WLANSAP_CancelRemainOnChannel(
272 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
273 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700274
Jeff Johnson32d95a32012-09-10 13:15:23 -0700275 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700276 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700277
c_hpothu7f63e882013-10-02 19:13:35 +0530278 if (0 >= status)
Jeff Johnson32d95a32012-09-10 13:15:23 -0700279 {
280 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530281 "%s: timeout waiting for cancel remain on channel ready indication %d",
282 __func__, status);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700283 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700284 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700285}
286
287int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
288{
289 int status = 0;
290 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
291
292 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
293 {
294 //Cancel Existing Remain On Channel
295 //If no action frame is pending
296 if( cfgState->remain_on_chan_ctx != NULL)
297 {
298 //Check whether Action Frame is pending or not
299 if( cfgState->buf == NULL)
300 {
301 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
302 }
303 else
304 {
305 hddLog( LOG1, "Cannot Cancel Existing Remain on Channel");
306 status = -EBUSY;
307 }
308 }
309 }
310 return status;
311}
312
313static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
314 struct net_device *dev,
315 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700316#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700317 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700318#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700319 unsigned int duration, u64 *cookie,
320 rem_on_channel_request_type_t request_type )
321{
322 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
323 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
324 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
325 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
326 __func__,pAdapter->device_mode);
327
Yue Maf49ba872013-08-19 12:04:25 -0700328#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700329 hddLog( LOG1,
330 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d",
331 chan->hw_value, chan->center_freq, channel_type, duration );
Yue Maf49ba872013-08-19 12:04:25 -0700332#else
333 hddLog( LOG1,
334 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d",
335 chan->hw_value, chan->center_freq, duration );
336#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700337 //Cancel existing remain On Channel if any
338 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700339
Jeff Johnsone7245742012-09-05 17:12:55 -0700340 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700341 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700342 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700343 * channel requets when Load/Unload is in progress*/
344 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
345 {
346 hddLog( LOGE,
347 "%s: Wlan Load/Unload is in progress", __func__);
348 return -EBUSY;
349 }
350
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700351 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
352 {
353 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
354 "%s:LOGP in Progress. Ignore!!!", __func__);
355 return -EAGAIN;
356 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700357 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
358 if( NULL == pRemainChanCtx )
359 {
360 hddLog(VOS_TRACE_LEVEL_FATAL,
361 "%s: Not able to allocate memory for Channel context",
362 __func__);
363 return -ENOMEM;
364 }
365
366 vos_mem_copy( &pRemainChanCtx->chan, chan,
367 sizeof(struct ieee80211_channel) );
368
Yue Maf49ba872013-08-19 12:04:25 -0700369#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700370 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700371#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700372 pRemainChanCtx->duration = duration;
vamsida0e5ab2013-12-26 14:33:27 +0530373 pRemainChanCtx->p2pRemOnChanTimeStamp = vos_timer_get_system_time();
Jeff Johnson295189b2012-06-20 16:38:30 -0700374 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800375 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700376 pRemainChanCtx->cookie = *cookie;
377 pRemainChanCtx->rem_on_chan_request = request_type;
378 cfgState->remain_on_chan_ctx = pRemainChanCtx;
379 cfgState->current_freq = chan->center_freq;
380
381 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
382
383 //call sme API to start remain on channel.
384 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700385 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
386 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700387 )
388 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700389 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700390 //call sme API to start remain on channel.
391 sme_RemainOnChannel(
392 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
393 chan->hw_value, duration,
Gopichand Nakkala924e4552013-05-08 19:18:14 +0530394 wlan_hdd_remain_on_channel_callback, pAdapter,
395 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700396
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800397 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
398 {
399 sme_RegisterMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
400 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
401 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 );
402 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700403
404 }
405 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
406 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
407 )
408 {
409 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700410 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700411 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
412 chan->hw_value, duration,
413 wlan_hdd_remain_on_channel_callback, pAdapter ))
414
415 {
416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
417 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
418 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700419 vos_mem_free (pRemainChanCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700420 return -EINVAL;
421 }
422
423
Jeff Johnson43971f52012-07-17 12:26:56 -0700424 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700425 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
426 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
427 NULL, 0 ))
428 {
429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
430 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
431 WLANSAP_CancelRemainOnChannel(
432 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
433 return -EINVAL;
434 }
435
436 }
437 return 0;
438
439}
440
441int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800442#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
443 struct wireless_dev *wdev,
444#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700445 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800446#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700447 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700448#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700449 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700450#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700451 unsigned int duration, u64 *cookie )
452{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800453#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
454 struct net_device *dev = wdev->netdev;
455#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700456 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700457 chan,
458#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
459 channel_type,
460#endif
461 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700462 REMAIN_ON_CHANNEL_REQUEST);
463}
464
465void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
466{
467 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
468 hdd_remain_on_chan_ctx_t* pRemainChanCtx = cfgState->remain_on_chan_ctx;
469
470 hddLog( LOG1, "Ready on chan ind");
471
472 if( pRemainChanCtx != NULL )
473 {
474 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
475 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800476 cfg80211_ready_on_channel(
477#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
478 pAdapter->dev->ieee80211_ptr,
479#else
480 pAdapter->dev,
481#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800482 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700483 &pRemainChanCtx->chan,
484#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
485 pRemainChanCtx->chan_type,
486#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700487 pRemainChanCtx->duration, GFP_KERNEL );
488 }
489#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
490 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request )
491 {
492 complete(&pAdapter->offchannel_tx_event);
493 }
494#endif
495 complete(&pAdapter->rem_on_chan_ready_event);
496 }
497 else
498 {
499 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
500 }
501 return;
502}
503
504int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800505#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
506 struct wireless_dev *wdev,
507#else
508 struct net_device *dev,
509#endif
510 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700511{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800512#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
513 struct net_device *dev = wdev->netdev;
514#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700515 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700516 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530517 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
518 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700519
520 hddLog( LOG1, "Cancel remain on channel req");
521
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530522 status = wlan_hdd_validate_context(pHddCtx);
523
524 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700525 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
527 "%s: HDD context is not valid", __func__);
528 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700529 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700530 /* FIXME cancel currently running remain on chan.
531 * Need to check cookie and cancel accordingly
532 */
533 if( (cfgState->remain_on_chan_ctx == NULL) ||
534 (cfgState->remain_on_chan_ctx->cookie != cookie) )
535 {
536 hddLog( LOGE,
537 "%s: No Remain on channel pending with specified cookie value",
538 __func__);
539 return -EINVAL;
540 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530541
542 /* wait until remain on channel ready event received
Jeff Johnson295189b2012-06-20 16:38:30 -0700543 * for already issued remain on channel request */
544 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
545 msecs_to_jiffies(WAIT_REM_CHAN_READY));
c_hpothu7f63e882013-10-02 19:13:35 +0530546 if (0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -0700547 {
c_hpothu7f63e882013-10-02 19:13:35 +0530548 hddLog( LOGE,
549 "%s: timeout waiting for remain on channel ready indication %d",
550 __func__, status);
Yue Ma4f55ef32014-01-23 16:45:33 -0800551
552 if (pHddCtx->isLogpInProgress)
553 {
554 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
555 "%s: LOGP in Progress. Ignore!!!", __func__);
556 return -EAGAIN;
557 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 }
559 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
560 /* Issue abort remain on chan request to sme.
561 * The remain on channel callback will make sure the remain_on_chan
562 * expired event is sent.
563 */
564 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700565 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
566 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700567 )
568 {
569 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700570 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
571 sessionId );
572 }
573 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
574 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
575 )
576 {
577 WLANSAP_CancelRemainOnChannel(
578 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
579 }
580 else
581 {
582 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
583 __func__, pAdapter->device_mode);
584 return -EIO;
585 }
c_hpothu7f63e882013-10-02 19:13:35 +0530586 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +0530588 if (0 >= status)
589 {
590 hddLog( LOGE,
591 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
592 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700593 return 0;
594}
595
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800596#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
597int wlan_hdd_action( struct wiphy *wiphy, struct wireless_dev *wdev,
598 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700599#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800600 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700601 bool channel_type_valid,
602#endif
603 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800604 const u8 *buf, size_t len, bool no_cck,
605 bool dont_wait_for_ack, u64 *cookie )
606#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700607int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
608 struct ieee80211_channel *chan, bool offchan,
609 enum nl80211_channel_type channel_type,
610 bool channel_type_valid, unsigned int wait,
611 const u8 *buf, size_t len, bool no_cck,
612 bool dont_wait_for_ack, u64 *cookie )
613#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
614int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
615 struct ieee80211_channel *chan, bool offchan,
616 enum nl80211_channel_type channel_type,
617 bool channel_type_valid, unsigned int wait,
618 const u8 *buf, size_t len, u64 *cookie )
619#else
620int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
621 struct ieee80211_channel *chan,
622 enum nl80211_channel_type channel_type,
623 bool channel_type_valid,
624 const u8 *buf, size_t len, u64 *cookie )
625#endif //LINUX_VERSION_CODE
626{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800627#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
628 struct net_device *dev = wdev->netdev;
629#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700630 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
631 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530632 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700633 tANI_U16 extendedWait = 0;
634 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
635 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
636 tActionFrmType actionFrmType;
637 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530638 int status;
Chet Lanctot186b5732013-03-18 10:26:30 -0700639#ifdef WLAN_FEATURE_11W
640 tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit
641#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700642
Jeff Johnson295189b2012-06-20 16:38:30 -0700643#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
644 hdd_adapter_t *goAdapter;
645#endif
646
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530647 status = wlan_hdd_validate_context(pHddCtx);
648
649 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800650 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
652 "%s: HDD context is not valid", __func__);
653 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800654 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530655
c_hpothu7f63e882013-10-02 19:13:35 +0530656 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
657 __func__, pAdapter->device_mode, type);
658
659
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700660#ifdef WLAN_FEATURE_P2P_DEBUG
661 if ((type == SIR_MAC_MGMT_FRAME) &&
662 (subType == SIR_MAC_MGMT_ACTION) &&
663 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
664 {
665 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800666 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700667 {
668 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
669 actionFrmType);
670 }
671 else
672 {
673 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
674 p2p_action_frame_type[actionFrmType]);
675 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
676 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
677 {
678 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
679 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800680 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700681 }
682 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
683 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
684 {
685 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
686 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
687 " completed state");
688 }
689 }
690 }
691#endif
692
Jeff Johnsone7245742012-09-05 17:12:55 -0700693#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
694 noack = dont_wait_for_ack;
695#endif
696
697 //If the wait is coming as 0 with off channel set
698 //then set the wait to 200 ms
699 if (offchan && !wait)
700 wait = ACTION_FRAME_DEFAULT_WAIT;
701
Jeff Johnson295189b2012-06-20 16:38:30 -0700702 //Call sme API to send out a action frame.
703 // OR can we send it directly through data path??
704 // After tx completion send tx status back.
705 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
706 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
707 )
708 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700709 if (type == SIR_MAC_MGMT_FRAME)
710 {
711 if (subType == SIR_MAC_MGMT_PROBE_RSP)
712 {
713 /* Drop Probe response recieved from supplicant, as for GO and
714 SAP PE itself sends probe response
715 */
716 goto err_rem_channel;
717 }
718 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
719 (subType == SIR_MAC_MGMT_DEAUTH))
720 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700721 /* During EAP failure or P2P Group Remove supplicant
722 * is sending del_station command to driver. From
723 * del_station function, Driver will send deauth frame to
724 * p2p client. No need to send disassoc frame from here.
725 * so Drop the frame here and send tx indication back to
726 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700727 */
728 tANI_U8 dstMac[ETH_ALEN] = {0};
729 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700730 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700731 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -0800732 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -0700733 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -0800734 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700735 goto err_rem_channel;
736 }
737 }
738 }
739
740 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800741 {
742 if ( !noack )
743 {
744 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
745 __func__);
746 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
747 }
748 else
749 {
750 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
751 __func__);
752 return -EBUSY;
753 }
754 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700755
756 hddLog( LOG1, "Action frame tx request");
757
758#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
759 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
760
761 //If GO adapter exists and operating on same frequency
762 //then we will not request remain on channel
763 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
764 == goAdapter->sessionCtx.ap.operatingChannel ) )
765 {
766 goto send_frame;
767 }
768#endif
769
770#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
771 if( offchan && wait)
772 {
773 int status;
774
775 // In case of P2P Client mode if we are already
776 // on the same channel then send the frame directly
777
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530778 //For remain on channel we issue a passive scan to firmware
779 //but currently there is no provision for dynamically extending
780 //the dwell time therefore cancelling the ongoing remain on channel
781 //and requesting for new one.
782 //The below logic will be extended for request type action frames if
783 //needed in future.
vamsi9bd92b72013-12-26 14:11:29 +0530784 if ((type == SIR_MAC_MGMT_FRAME) &&
Edhar, Mahesh Kumar42d648d2013-12-19 12:16:15 +0530785 (subType == SIR_MAC_MGMT_ACTION) &&
vamsi9bd92b72013-12-26 14:11:29 +0530786 hdd_p2p_is_action_type_rsp(&buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET]) &&
787 cfgState->remain_on_chan_ctx &&
788 cfgState->current_freq == chan->center_freq ) {
789
vamsida0e5ab2013-12-26 14:33:27 +0530790 tANI_U32 current_time = vos_timer_get_system_time();
791
792 // In case of P2P Client mode if we are already
793 // on the same channel then send the frame directly only if
794 // there is enough remain on channel time left.
795 // If remain on channel time is about to expire in next 20ms
796 // then dont send frame without a fresh remain on channel as this
797 // may cause a race condition with lim remain_on_channel_timer
798 // which might expire by the time the action frame reaches lim
799 // layer.
800 if ((int)(cfgState->remain_on_chan_ctx->duration -
801 (current_time -
802 cfgState->remain_on_chan_ctx->p2pRemOnChanTimeStamp)) <
803 ESTIMATED_ROC_DUR_REQD_FOR_ACTION_TX)
804 {
805 hddLog(LOG1,"action frame: Extending the RoC");
806 status = wlan_hdd_check_remain_on_channel(pAdapter);
807 if ( !status )
808 {
809 pAdapter->internalCancelRemainOnChReq = VOS_TRUE;
810 }
811 else
812 {
813 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
814 "Failed to cancel the existing RoC");
815 }
816 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530817 }
818
Jeff Johnson295189b2012-06-20 16:38:30 -0700819 if((cfgState->remain_on_chan_ctx != NULL) &&
820 (cfgState->current_freq == chan->center_freq)
821 )
822 {
Arif Hussain6d2a3322013-11-17 19:50:10 -0800823 hddLog(LOG1,"action frame: extending the wait time");
Jeff Johnsone7245742012-09-05 17:12:55 -0700824 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700825 goto send_frame;
826 }
Agarwal Ashish963bf002013-12-10 16:57:10 +0530827
Jeff Johnson295189b2012-06-20 16:38:30 -0700828 INIT_COMPLETION(pAdapter->offchannel_tx_event);
829
830 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700831 chan,
832#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
833 channel_type,
834#endif
835 wait, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700836 OFF_CHANNEL_ACTION_TX);
837
838 if(0 != status)
839 {
840 if( (-EBUSY == status) &&
841 (cfgState->current_freq == chan->center_freq) )
842 {
843 goto send_frame;
844 }
845 goto err_rem_channel;
846 }
Madan Mohan Koyyalamudi87673f62013-09-27 02:39:27 +0530847 /* This will extend timer in LIM when sending Any action frame
848 * It will cover remain on channel timer till next action frame
849 * in rx direction.
850 */
851 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700852 /* Wait for driver to be ready on the requested channel */
853 status = wait_for_completion_interruptible_timeout(
854 &pAdapter->offchannel_tx_event,
855 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +0530856 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -0700857 {
c_hpothu7f63e882013-10-02 19:13:35 +0530858 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -0700859 goto err_rem_channel;
860 }
861 }
862 else if ( offchan )
863 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700864 /* Check before sending action frame
865 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -0700866 if(NULL == cfgState->remain_on_chan_ctx)
867 {
868 goto err_rem_channel;
869 }
870 }
871 send_frame:
872#endif
873
Jeff Johnsone7245742012-09-05 17:12:55 -0700874 if(!noack)
875 {
876 cfgState->buf = vos_mem_malloc( len ); //buf;
877 if( cfgState->buf == NULL )
878 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -0700879
Jeff Johnsone7245742012-09-05 17:12:55 -0700880 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -0700881
Jeff Johnsone7245742012-09-05 17:12:55 -0700882 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700883
884#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700885 if( cfgState->remain_on_chan_ctx )
886 {
887 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
888 *cookie = cfgState->action_cookie;
889 }
890 else
891 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700892#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800893 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -0700894 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -0700895#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700896 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700897#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700898 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700899
900 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700901 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
902 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700903 )
904 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700905 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800906
Jeff Johnsone7245742012-09-05 17:12:55 -0700907 if ((type == SIR_MAC_MGMT_FRAME) &&
908 (subType == SIR_MAC_MGMT_ACTION) &&
909 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -0700910 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700911 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -0800912 hddLog(LOG1, "Tx Action Frame %u", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -0700913 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -0700914 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700915 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Arif Hussain6d2a3322013-11-17 19:50:10 -0800916 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -0700917 }
918 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
919 {
920 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Arif Hussain6d2a3322013-11-17 19:50:10 -0800921 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700922 }
923 }
Chet Lanctot186b5732013-03-18 10:26:30 -0700924#ifdef WLAN_FEATURE_11W
925 if ((type == SIR_MAC_MGMT_FRAME) &&
926 (subType == SIR_MAC_MGMT_ACTION) &&
927 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME))
928 {
929 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
930 "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query");
931 // Since this is an SA Query Action Frame, we have to protect it
932 WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]);
933 }
934#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700935 if (eHAL_STATUS_SUCCESS !=
936 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -0700937 sessionId, buf, len, extendedWait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -0700938 {
939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
940 "%s: sme_sendAction returned fail", __func__);
941 goto err;
942 }
943 }
944 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
945 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
946 )
947 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700948 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700949 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700950 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700951 {
952 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
953 "%s: WLANSAP_SendAction returned fail", __func__);
954 goto err;
955 }
956 }
957
958 return 0;
959err:
Jeff Johnsone7245742012-09-05 17:12:55 -0700960 if(!noack)
961 {
962 hdd_sendActionCnf( pAdapter, FALSE );
963 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700964 return 0;
965err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800966 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800967 cfg80211_mgmt_tx_status(
968#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
969 pAdapter->dev->ieee80211_ptr,
970#else
971 pAdapter->dev,
972#endif
973 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -0700974 return 0;
975}
976
977#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800978#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
979int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
980 struct wireless_dev *wdev,
981 u64 cookie)
982{
983 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
984}
985#else
986int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -0700987 struct net_device *dev,
988 u64 cookie)
989{
990 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
991}
992#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800993#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700994
995void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
996{
997 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
998
Jeff Johnsone7245742012-09-05 17:12:55 -0700999 cfgState->actionFrmState = HDD_IDLE;
1000
Jeff Johnson295189b2012-06-20 16:38:30 -07001001 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1002 if( NULL == cfgState->buf )
1003 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001004 return;
1005 }
1006
1007 /* If skb is NULL it means this packet was received on CFG80211 interface
1008 * else it was received on Monitor interface */
1009 if( cfgState->skb == NULL )
1010 {
1011 /*
1012 * buf is the same pointer it passed us to send. Since we are sending
1013 * it through control path, we use different buffers.
1014 * In case of mac80211, they just push it to the skb and pass the same
1015 * data while sending tx ack status.
1016 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001017 cfg80211_mgmt_tx_status(
1018#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1019 pAdapter->dev->ieee80211_ptr,
1020#else
1021 pAdapter->dev,
1022#endif
1023 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001024 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1025 vos_mem_free( cfgState->buf );
1026 cfgState->buf = NULL;
1027 }
1028 else
1029 {
1030 hdd_adapter_t* pMonAdapter =
1031 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1032 if( pMonAdapter == NULL )
1033 {
1034 hddLog( LOGE, "Not able to get Monitor Adapter");
1035 cfgState->skb = NULL;
1036 vos_mem_free( cfgState->buf );
1037 cfgState->buf = NULL;
1038 complete(&pAdapter->tx_action_cnf_event);
1039 return;
1040 }
1041 /* Send TX completion feedback over monitor interface. */
1042 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1043 cfgState->skb = NULL;
1044 vos_mem_free( cfgState->buf );
1045 cfgState->buf = NULL;
1046 /* Look for the next Mgmt packet to TX */
1047 hdd_mon_tx_mgmt_pkt(pAdapter);
1048 }
1049 complete(&pAdapter->tx_action_cnf_event);
1050}
1051
1052/**
1053 * hdd_setP2pNoa
1054 *
1055 *FUNCTION:
1056 * This function is called from hdd_hostapd_ioctl function when Driver
1057 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1058 *
1059 *LOGIC:
1060 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1061 *
1062 *ASSUMPTIONS:
1063 *
1064 *
1065 *NOTE:
1066 *
1067 * @param dev Pointer to net device structure
1068 * @param command Pointer to command
1069 *
1070 * @return Status
1071 */
1072
1073int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1074{
1075 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1076 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1077 VOS_STATUS status = VOS_STATUS_SUCCESS;
1078 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001079 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001080 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001081 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001082
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001083 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001084 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301085 {
1086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1087 "%s: strnchr failed to find delimeter",__func__);
1088 return -EINVAL;
1089 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001090 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001091 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1092 if (ret < 3)
1093 {
1094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1095 "%s: P2P_SET GO NoA: fail to read param "
1096 "count=%d duration=%d interval=%d \n",
1097 __func__, count, start_time, duration);
1098 return -EINVAL;
1099 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001100 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001101 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001102 __func__, count, start_time, duration);
1103 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001104 /* PS Selection
1105 * Periodic NoA (2)
1106 * Single NOA (4)
1107 */
1108 NoA.opp_ps = 0;
1109 NoA.ctWindow = 0;
1110 if (count == 1)
1111 {
1112 NoA.duration = 0;
1113 NoA.single_noa_duration = duration;
1114 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1115 }
1116 else
1117 {
1118 NoA.duration = duration;
1119 NoA.single_noa_duration = 0;
1120 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1121 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001122 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001123 NoA.count = count;
1124 NoA.sessionid = pAdapter->sessionId;
1125
1126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1127 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1128 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001129 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001130 NoA.ctWindow, NoA.duration, NoA.interval,
1131 NoA.count, NoA.single_noa_duration,
1132 NoA.psSelection);
1133
1134 sme_p2pSetPs(hHal, &NoA);
1135 return status;
1136}
1137
1138/**
1139 * hdd_setP2pOpps
1140 *
1141 *FUNCTION:
1142 * This function is called from hdd_hostapd_ioctl function when Driver
1143 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1144 *
1145 *LOGIC:
1146 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1147 *
1148 *ASSUMPTIONS:
1149 *
1150 *
1151 *NOTE:
1152 *
1153 * @param dev Pointer to net device structure
1154 * @param command Pointer to command
1155 *
1156 * @return Status
1157 */
1158
1159int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1160{
1161 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1162 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1163 VOS_STATUS status = VOS_STATUS_SUCCESS;
1164 tP2pPsConfig NoA;
1165 char *param;
1166 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001167 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001168
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001169 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001170 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301171 {
1172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1173 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001174 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301175 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001177 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1178 if (ret < 3)
1179 {
1180 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1181 "%s: P2P_SET GO PS: fail to read param "
1182 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1183 __func__, legacy_ps, opp_ps, ctwindow);
1184 return -EINVAL;
1185 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001186 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001187 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001188 __func__, legacy_ps, opp_ps, ctwindow);
1189
1190 /* PS Selection
1191 * Opportunistic Power Save (1)
1192 */
1193
1194 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1195 * When user want to set ctWindow during that time other parameters
1196 * values are coming from wpa_supplicant as -1.
1197 * Example : User want to set ctWindow with 30 then wpa_cli command :
1198 * P2P_SET ctwindow 30
1199 * Command Received at hdd_hostapd_ioctl is as below:
1200 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
1201 */
1202 if (ctwindow != -1)
1203 {
1204
1205 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001206 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001207 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1208
1209 if (ctwindow != pAdapter->ctw)
1210 {
1211 pAdapter->ctw = ctwindow;
1212
1213 if(pAdapter->ops)
1214 {
1215 NoA.opp_ps = pAdapter->ops;
1216 NoA.ctWindow = pAdapter->ctw;
1217 NoA.duration = 0;
1218 NoA.single_noa_duration = 0;
1219 NoA.interval = 0;
1220 NoA.count = 0;
1221 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1222 NoA.sessionid = pAdapter->sessionId;
1223
1224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1225 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1226 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001227 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001228 NoA.ctWindow, NoA.duration, NoA.interval,
1229 NoA.count, NoA.single_noa_duration,
1230 NoA.psSelection);
1231
1232 sme_p2pSetPs(hHal, &NoA);
1233 }
1234 return 0;
1235 }
1236 }
1237
1238 if (opp_ps != -1)
1239 {
1240 pAdapter->ops = opp_ps;
1241
1242 if ((opp_ps != -1) && (pAdapter->ctw))
1243 {
1244 NoA.opp_ps = opp_ps;
1245 NoA.ctWindow = pAdapter->ctw;
1246 NoA.duration = 0;
1247 NoA.single_noa_duration = 0;
1248 NoA.interval = 0;
1249 NoA.count = 0;
1250 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1251 NoA.sessionid = pAdapter->sessionId;
1252
1253 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1254 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1255 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001256 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001257 NoA.ctWindow, NoA.duration, NoA.interval,
1258 NoA.count, NoA.single_noa_duration,
1259 NoA.psSelection);
1260
1261 sme_p2pSetPs(hHal, &NoA);
1262 }
1263 }
1264 return status;
1265}
1266
1267int hdd_setP2pPs( struct net_device *dev, void *msgData )
1268{
1269 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1270 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1271 VOS_STATUS status = VOS_STATUS_SUCCESS;
1272 tP2pPsConfig NoA;
1273 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1274
1275 NoA.opp_ps = pappNoA->opp_ps;
1276 NoA.ctWindow = pappNoA->ctWindow;
1277 NoA.duration = pappNoA->duration;
1278 NoA.interval = pappNoA->interval;
1279 NoA.count = pappNoA->count;
1280 NoA.single_noa_duration = pappNoA->single_noa_duration;
1281 NoA.psSelection = pappNoA->psSelection;
1282 NoA.sessionid = pAdapter->sessionId;
1283
1284 sme_p2pSetPs(hHal, &NoA);
1285 return status;
1286}
Jeff Johnson295189b2012-06-20 16:38:30 -07001287
1288static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1289{
1290 tANI_U8 sessionType;
1291
1292 switch( type )
1293 {
1294 case NL80211_IFTYPE_AP:
1295 sessionType = WLAN_HDD_SOFTAP;
1296 break;
1297 case NL80211_IFTYPE_P2P_GO:
1298 sessionType = WLAN_HDD_P2P_GO;
1299 break;
1300 case NL80211_IFTYPE_P2P_CLIENT:
1301 sessionType = WLAN_HDD_P2P_CLIENT;
1302 break;
1303 case NL80211_IFTYPE_STATION:
1304 sessionType = WLAN_HDD_INFRA_STATION;
1305 break;
1306 case NL80211_IFTYPE_MONITOR:
1307 sessionType = WLAN_HDD_MONITOR;
1308 break;
1309 default:
1310 sessionType = WLAN_HDD_INFRA_STATION;
1311 break;
1312 }
1313
1314 return sessionType;
1315}
1316
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001317#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1318struct wireless_dev* wlan_hdd_add_virtual_intf(
1319 struct wiphy *wiphy, const char *name,
1320 enum nl80211_iftype type,
1321 u32 *flags, struct vif_params *params )
1322#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1323struct wireless_dev* wlan_hdd_add_virtual_intf(
1324 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1325 u32 *flags, struct vif_params *params )
1326#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001327struct net_device* wlan_hdd_add_virtual_intf(
1328 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1329 u32 *flags, struct vif_params *params )
1330#else
1331int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1332 enum nl80211_iftype type,
1333 u32 *flags, struct vif_params *params )
1334#endif
1335{
1336 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1337 hdd_adapter_t* pAdapter = NULL;
1338
1339 ENTER();
1340
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001341 if(hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
1342 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001343 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001344 "interfaces of same type are not supported currently.",__func__, type);
Jeff Johnsond13512a2012-07-17 11:42:19 -07001345 return NULL;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001346 }
1347
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001348 if (pHddCtx->isLogpInProgress)
1349 {
1350 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1351 "%s:LOGP in Progress. Ignore!!!", __func__);
1352#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1353 return NULL;
1354#else
1355 return -EAGAIN;
1356#endif
1357 }
Kiet Lam04e26912013-10-18 20:13:38 +05301358 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1359 ((NL80211_IFTYPE_P2P_GO == type) ||
1360 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001361 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001362 /* Generate the P2P Interface Address. this address must be
1363 * different from the P2P Device Address.
1364 */
1365 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1366 p2pDeviceAddress.bytes[4] ^= 0x80;
1367 pAdapter = hdd_open_adapter( pHddCtx,
1368 wlan_hdd_get_session_type(type),
1369 name, p2pDeviceAddress.bytes,
1370 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001371 }
1372 else
1373 {
1374 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1375 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1376 }
1377
1378 if( NULL == pAdapter)
1379 {
1380 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1381#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1382 return NULL;
1383#else
1384 return -EINVAL;
1385#endif
1386 }
1387 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001388#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1389 return pAdapter->dev->ieee80211_ptr;
1390#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001391 return pAdapter->dev;
1392#else
1393 return 0;
1394#endif
1395}
1396
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001397#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1398int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1399#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001400int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001401#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001402{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001403#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1404 struct net_device *dev = wdev->netdev;
1405#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301406 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1407 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1408 int status;
1409 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001410
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301411 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1412 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001413
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301414 status = wlan_hdd_validate_context(pHddCtx);
1415
1416 if (0 != status)
1417 {
1418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1419 "%s: HDD context is not valid", __func__);
1420 return status;
1421 }
1422
1423 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001424 pVirtAdapter->macAddressCurrent.bytes );
1425
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301426 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1427 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1428 EXIT();
1429 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001430}
1431
1432void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001433 tANI_U32 nFrameLength,
1434 tANI_U8* pbFrames,
Jeff Johnson295189b2012-06-20 16:38:30 -07001435 tANI_U8 frameType )
1436{
1437 //Indicate a Frame over Monitor Intf.
1438 int rxstat;
1439 struct sk_buff *skb = NULL;
1440 int needed_headroom = 0;
1441 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1442 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001443#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001444#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1445 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1446#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001447#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001448 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1449
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001450 if (NULL == pbFrames)
1451 {
1452 hddLog(LOGE, FL("NULL frame pointer"));
1453 return;
1454 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001455
1456 /* room for the radiotap header based on driver features
1457 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1458 * RX flags.
1459 * */
1460 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1461
1462 //alloc skb here
1463 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1464 if (unlikely(NULL == skb))
1465 {
1466 hddLog( LOGW, FL("Unable to allocate skb"));
1467 return;
1468 }
1469 skb_reserve(skb, VPKT_SIZE_BUFFER);
1470 if (unlikely(skb_headroom(skb) < nFrameLength))
1471 {
1472 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1473 "HDD [%d]: Insufficient headroom, "
1474 "head[%p], data[%p], req[%d]",
1475 __LINE__, skb->head, skb->data, nFrameLength);
1476 kfree_skb(skb);
1477 return ;
1478 }
1479 // actually push the data
1480 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1481 /* prepend radiotap information */
1482 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1483 {
1484 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1485 //free skb
1486 kfree_skb(skb);
1487 return ;
1488 }
1489
1490 skb_reset_mac_header( skb );
1491 skb->dev = pMonAdapter->dev;
1492 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001493 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001494#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001495#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001496 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001497#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001498#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001499 rxstat = netif_rx_ni(skb);
1500 if( NET_RX_SUCCESS == rxstat )
1501 {
1502 hddLog( LOG1, FL("Success"));
1503 }
1504 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301505 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07001506
1507 return ;
1508}
1509
1510void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
1511 tANI_U32 nFrameLength,
1512 tANI_U8* pbFrames,
1513 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301514 tANI_U32 rxChan,
1515 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001516{
1517 tANI_U16 freq;
Jeff Johnsone7245742012-09-05 17:12:55 -07001518 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001519 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001520 tActionFrmType actionFrmType;
1521 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301522 hdd_context_t *pHddCtx = NULL;
1523 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001524
Arif Hussain6d2a3322013-11-17 19:50:10 -08001525 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001526 __func__, frameType, nFrameLength);
1527
1528 if (NULL == pAdapter)
1529 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001530 hddLog(LOGE, FL("pAdapter is NULL"));
1531 return;
1532 }
1533
1534 if (0 == nFrameLength)
1535 {
1536 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
1537 return;
1538 }
1539
1540 if (NULL == pbFrames)
1541 {
1542 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001543 return;
1544 }
1545
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001546 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1547 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1548
1549 /* Get pAdapter from Destination mac address of the frame */
1550 if ((type == SIR_MAC_MGMT_FRAME) &&
1551 (subType != SIR_MAC_MGMT_PROBE_REQ))
1552 {
1553 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1554 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1555 if (NULL == pAdapter)
1556 {
1557 /* Under assumtion that we don't receive any action frame
1558 * with BCST as destination we dropping action frame
1559 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001560 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1561 MAC_ADDRESS_STR ,
1562 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1563 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08001564 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001565 return;
1566 }
1567 }
1568
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001569
Jeff Johnson295189b2012-06-20 16:38:30 -07001570 if (NULL == pAdapter->dev)
1571 {
1572 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1573 return;
1574 }
1575
1576 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1577 {
1578 hddLog( LOGE, FL("pAdapter has invalid magic"));
1579 return;
1580 }
1581
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301582 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1583 if (NULL == pHddCtx)
1584 {
1585 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
1586 return;
1587 }
1588
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001589 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1590 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001591 {
1592 hdd_adapter_t *pMonAdapter =
1593 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1594
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001595 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001596 {
1597 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1598 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1599 pbFrames, frameType);
1600 return;
1601 }
1602 }
1603
1604 //Channel indicated may be wrong. TODO
1605 //Indicate an action frame.
1606 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1607 {
1608 freq = ieee80211_channel_to_frequency( rxChan,
1609 IEEE80211_BAND_2GHZ);
1610 }
1611 else
1612 {
1613 freq = ieee80211_channel_to_frequency( rxChan,
1614 IEEE80211_BAND_5GHZ);
1615 }
1616
Jeff Johnsone7245742012-09-05 17:12:55 -07001617 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1618
1619 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001620 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001621 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001622 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1623 {
1624 // public action frame
1625 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001626 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 -08001627 // P2P action frames
1628 {
1629 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08001630 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001631#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001632 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1633 {
1634 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1635 actionFrmType);
1636 }
1637 else
1638 {
1639 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1640 p2p_action_frame_type[actionFrmType]);
1641 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1642 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1643 {
1644 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1645 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001646 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001647 }
1648 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1649 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1650 {
1651 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001652 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1653 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001654 }
1655 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1656 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1657 {
1658 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1659 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1660 " completed state Autonomous GO formation");
1661 }
1662 }
1663#endif
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301664 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) ||
1665 (actionFrmType == WLAN_HDD_GO_NEG_REQ) )
1666 {
1667 pScanInfo = &pHddCtx->scan_info;
1668 if((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
1669 {
1670 hddLog(LOGE,"Action frame received when Scanning is in"
1671 " progress. Abort Scan.");
1672 hdd_abort_mac_scan(pAdapter->pHddCtx,
1673 pAdapter->sessionId);
1674 }
1675 }
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001676 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
1677 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
1678 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
1679 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
1680 {
1681 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
1682 __func__);
1683 hdd_sendActionCnf(pAdapter, TRUE);
1684 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001685 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001686#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001687 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 -07001688 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001689 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
1690#ifdef WLAN_FEATURE_TDLS_DEBUG
1691 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
1692 MAC_ADDR_ARRAY(mac),rxRssi);
1693#endif
1694 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
1695 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001696 }
1697#endif
1698 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001699#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001700 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
1701 {
1702 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
1703 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
1704 {
1705 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
1706 actionFrmType);
1707 }
1708 else
1709 {
1710 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
1711 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001712 }
1713 }
1714#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07001715 }
1716
Jeff Johnson295189b2012-06-20 16:38:30 -07001717 //Indicate Frame Over Normal Interface
1718 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
1719
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001720#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1721 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
1722 pbFrames, nFrameLength,
1723 GFP_ATOMIC );
1724#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001725 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
1726 pbFrames, nFrameLength,
1727 GFP_ATOMIC );
1728#else
1729 cfg80211_rx_mgmt( pAdapter->dev, freq,
1730 pbFrames, nFrameLength,
1731 GFP_ATOMIC );
1732#endif //LINUX_VERSION_CODE
1733}
1734
1735/*
1736 * ieee80211_add_rx_radiotap_header - add radiotap header
1737 */
1738static int hdd_wlan_add_rx_radiotap_hdr (
1739 struct sk_buff *skb, int rtap_len, int flag )
1740{
1741 u8 rtap_temp[20] = {0};
1742 struct ieee80211_radiotap_header *rthdr;
1743 unsigned char *pos;
1744 u16 rx_flags = 0;
1745
1746 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
1747
1748 /* radiotap header, set always present flags */
1749 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
1750 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
1751 rthdr->it_len = cpu_to_le16(rtap_len);
1752
1753 pos = (unsigned char *) (rthdr + 1);
1754
1755 /* the order of the following fields is important */
1756
1757 /* IEEE80211_RADIOTAP_FLAGS */
1758 *pos = 0;
1759 pos++;
1760
1761 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
1762 /* ensure 2 byte alignment for the 2 byte field as required */
1763 if ((pos - (u8 *)rthdr) & 1)
1764 pos++;
1765 put_unaligned_le16(rx_flags, pos);
1766 pos += 2;
1767
1768 // actually push the data
1769 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
1770
1771 return 0;
1772}
1773
1774static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
1775 hdd_cfg80211_state_t* cfgState,
1776 tANI_BOOLEAN actionSendSuccess )
1777{
1778 struct ieee80211_radiotap_header *rthdr;
1779 unsigned char *pos;
1780 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001781#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001782#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1783 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
1784#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001785#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001786
1787 /* 2 Byte for TX flags and 1 Byte for Retry count */
1788 u32 rtHdrLen = sizeof(*rthdr) + 3;
1789
1790 u8 *data;
1791
1792 /* We have to return skb with Data starting with MAC header. We have
1793 * copied SKB data starting with MAC header to cfgState->buf. We will pull
1794 * entire skb->len from skb and then we will push cfgState->buf to skb
1795 * */
1796 if( NULL == skb_pull(skb, skb->len) )
1797 {
1798 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
1799 kfree_skb(cfgState->skb);
1800 return;
1801 }
1802
1803 data = skb_push( skb, cfgState->len );
1804
1805 if (data == NULL)
1806 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08001807 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001808 kfree_skb( cfgState->skb );
1809 return;
1810 }
1811
1812 memcpy( data, cfgState->buf, cfgState->len );
1813
1814 /* send frame to monitor interfaces now */
1815 if( skb_headroom(skb) < rtHdrLen )
1816 {
1817 hddLog( LOGE, FL("No headroom for rtap header"));
1818 kfree_skb(cfgState->skb);
1819 return;
1820 }
1821
1822 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
1823
1824 memset( rthdr, 0, rtHdrLen );
1825 rthdr->it_len = cpu_to_le16( rtHdrLen );
1826 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
1827 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
1828 );
1829
1830 pos = (unsigned char *)( rthdr+1 );
1831
1832 // Fill TX flags
1833 *pos = actionSendSuccess;
1834 pos += 2;
1835
1836 // Fill retry count
1837 *pos = 0;
1838 pos++;
1839
1840 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001841 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001842 skb->pkt_type = PACKET_OTHERHOST;
1843 skb->protocol = htons(ETH_P_802_2);
1844 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001845#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001846#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001847 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001848#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001849#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001850 if (in_interrupt())
1851 netif_rx( skb );
1852 else
1853 netif_rx_ni( skb );
1854
1855 /* Enable Queues which we have disabled earlier */
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05301856 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07001857
1858}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05301859