blob: f424fcccb0c1d3fff6a6d14491c6524f212a54a0 [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 );
121
Jeff Johnson295189b2012-06-20 16:38:30 -0700122eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
123 eHalStatus status )
124{
125 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700126 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
127 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
128
129 if( pRemainChanCtx == NULL )
130 {
131 hddLog( LOGW,
132 "%s: No Rem on channel pending for which Rsp is received", __func__);
133 return eHAL_STATUS_SUCCESS;
134 }
135
136 hddLog( LOG1, "Received remain on channel rsp");
137
138 cfgState->remain_on_chan_ctx = NULL;
139
140 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
141 {
142 if( cfgState->buf )
143 {
144 hddLog( LOGP,
145 "%s: We need to receive yet an ack from one of tx packet",
146 __func__);
147 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800148 cfg80211_remain_on_channel_expired(
149#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
150 pRemainChanCtx->dev->ieee80211_ptr,
151#else
152 pRemainChanCtx->dev,
153#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700154 pRemainChanCtx->cookie,
155 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700156#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
157 pRemainChanCtx->chan_type,
158#endif
159 GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -0700160 }
161
Jeff Johnson295189b2012-06-20 16:38:30 -0700162
163 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700164 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
165 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700166 )
167 {
168 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800169 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
170 {
171 sme_DeregisterMgmtFrame(
172 hHal, sessionId,
173 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
174 NULL, 0 );
175 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700176 }
177 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
178 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
179 )
180 {
181 WLANSAP_DeRegisterMgmtFrame(
182 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
183 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
184 NULL, 0 );
185 }
186
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800187 vos_mem_free( pRemainChanCtx );
Jeff Johnson295189b2012-06-20 16:38:30 -0700188 complete(&pAdapter->cancel_rem_on_chan_var);
189 return eHAL_STATUS_SUCCESS;
190}
191
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -0800192void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700193{
Jeff Johnson295189b2012-06-20 16:38:30 -0700194 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
195 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700196
Jeff Johnson32d95a32012-09-10 13:15:23 -0700197 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700198 {
Jeff Johnson32d95a32012-09-10 13:15:23 -0700199 hddLog( LOG1, "Cancel Existing Remain on Channel");
200
201 /* Wait till remain on channel ready indication before issuing cancel
202 * remain on channel request, otherwise if remain on channel not
203 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700204 * will be in unknown state.
205 */
206 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
207 msecs_to_jiffies(WAIT_REM_CHAN_READY));
208 if (!status)
209 {
210 hddLog( LOGE,
211 "%s: timeout waiting for remain on channel ready indication",
212 __func__);
213 }
214
215 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700216
Jeff Johnson295189b2012-06-20 16:38:30 -0700217 /* Issue abort remain on chan request to sme.
218 * The remain on channel callback will make sure the remain_on_chan
219 * expired event is sent.
220 */
221 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700222 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
223 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700224 )
225 {
226 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
227 pAdapter->sessionId );
228 }
229 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
230 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
231 )
232 {
233 WLANSAP_CancelRemainOnChannel(
234 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
235 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700236
Jeff Johnson32d95a32012-09-10 13:15:23 -0700237 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700239
240 if (!status)
241 {
242 hddLog( LOGE,
243 "%s: timeout waiting for cancel remain on channel ready indication",
244 __func__);
245 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700246 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700247}
248
249int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
250{
251 int status = 0;
252 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
253
254 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
255 {
256 //Cancel Existing Remain On Channel
257 //If no action frame is pending
258 if( cfgState->remain_on_chan_ctx != NULL)
259 {
260 //Check whether Action Frame is pending or not
261 if( cfgState->buf == NULL)
262 {
263 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
264 }
265 else
266 {
267 hddLog( LOG1, "Cannot Cancel Existing Remain on Channel");
268 status = -EBUSY;
269 }
270 }
271 }
272 return status;
273}
274
275static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
276 struct net_device *dev,
277 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700278#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700279 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700280#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700281 unsigned int duration, u64 *cookie,
282 rem_on_channel_request_type_t request_type )
283{
284 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
285 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
286 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
287 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
288 __func__,pAdapter->device_mode);
289
Yue Maf49ba872013-08-19 12:04:25 -0700290#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700291 hddLog( LOG1,
292 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d",
293 chan->hw_value, chan->center_freq, channel_type, duration );
Yue Maf49ba872013-08-19 12:04:25 -0700294#else
295 hddLog( LOG1,
296 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d",
297 chan->hw_value, chan->center_freq, duration );
298#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700299 //Cancel existing remain On Channel if any
300 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700301
Jeff Johnsone7245742012-09-05 17:12:55 -0700302 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700304 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700305 * channel requets when Load/Unload is in progress*/
306 if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
307 {
308 hddLog( LOGE,
309 "%s: Wlan Load/Unload is in progress", __func__);
310 return -EBUSY;
311 }
312
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700313 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
314 {
315 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
316 "%s:LOGP in Progress. Ignore!!!", __func__);
317 return -EAGAIN;
318 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700319 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
320 if( NULL == pRemainChanCtx )
321 {
322 hddLog(VOS_TRACE_LEVEL_FATAL,
323 "%s: Not able to allocate memory for Channel context",
324 __func__);
325 return -ENOMEM;
326 }
327
328 vos_mem_copy( &pRemainChanCtx->chan, chan,
329 sizeof(struct ieee80211_channel) );
330
Yue Maf49ba872013-08-19 12:04:25 -0700331#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700332 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700333#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700334 pRemainChanCtx->duration = duration;
335 pRemainChanCtx->dev = dev;
336 *cookie = (tANI_U32) pRemainChanCtx;
337 pRemainChanCtx->cookie = *cookie;
338 pRemainChanCtx->rem_on_chan_request = request_type;
339 cfgState->remain_on_chan_ctx = pRemainChanCtx;
340 cfgState->current_freq = chan->center_freq;
341
342 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
343
344 //call sme API to start remain on channel.
345 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700346 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
347 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700348 )
349 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700350 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700351 //call sme API to start remain on channel.
352 sme_RemainOnChannel(
353 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
354 chan->hw_value, duration,
Gopichand Nakkala924e4552013-05-08 19:18:14 +0530355 wlan_hdd_remain_on_channel_callback, pAdapter,
356 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700357
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800358 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
359 {
360 sme_RegisterMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
361 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
362 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 );
363 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700364
365 }
366 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
367 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
368 )
369 {
370 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700371 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700372 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
373 chan->hw_value, duration,
374 wlan_hdd_remain_on_channel_callback, pAdapter ))
375
376 {
377 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
378 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
379 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700380 vos_mem_free (pRemainChanCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700381 return -EINVAL;
382 }
383
384
Jeff Johnson43971f52012-07-17 12:26:56 -0700385 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700386 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
387 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
388 NULL, 0 ))
389 {
390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
391 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
392 WLANSAP_CancelRemainOnChannel(
393 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
394 return -EINVAL;
395 }
396
397 }
398 return 0;
399
400}
401
402int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800403#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
404 struct wireless_dev *wdev,
405#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700406 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800407#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700408 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700409#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700410 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700411#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700412 unsigned int duration, u64 *cookie )
413{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800414#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
415 struct net_device *dev = wdev->netdev;
416#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700417 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700418 chan,
419#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
420 channel_type,
421#endif
422 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700423 REMAIN_ON_CHANNEL_REQUEST);
424}
425
426void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
427{
428 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
429 hdd_remain_on_chan_ctx_t* pRemainChanCtx = cfgState->remain_on_chan_ctx;
430
431 hddLog( LOG1, "Ready on chan ind");
432
433 if( pRemainChanCtx != NULL )
434 {
435 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
436 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800437 cfg80211_ready_on_channel(
438#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
439 pAdapter->dev->ieee80211_ptr,
440#else
441 pAdapter->dev,
442#endif
443 (tANI_U32)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700444 &pRemainChanCtx->chan,
445#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
446 pRemainChanCtx->chan_type,
447#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700448 pRemainChanCtx->duration, GFP_KERNEL );
449 }
450#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
451 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request )
452 {
453 complete(&pAdapter->offchannel_tx_event);
454 }
455#endif
456 complete(&pAdapter->rem_on_chan_ready_event);
457 }
458 else
459 {
460 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
461 }
462 return;
463}
464
465int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800466#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
467 struct wireless_dev *wdev,
468#else
469 struct net_device *dev,
470#endif
471 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700472{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800473#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
474 struct net_device *dev = wdev->netdev;
475#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700476 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700477 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530478 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
479 int status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700480
481 hddLog( LOG1, "Cancel remain on channel req");
482
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530483 status = wlan_hdd_validate_context(pHddCtx);
484
485 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700486 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530487 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
488 "%s: HDD context is not valid", __func__);
489 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700490 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700491 /* FIXME cancel currently running remain on chan.
492 * Need to check cookie and cancel accordingly
493 */
494 if( (cfgState->remain_on_chan_ctx == NULL) ||
495 (cfgState->remain_on_chan_ctx->cookie != cookie) )
496 {
497 hddLog( LOGE,
498 "%s: No Remain on channel pending with specified cookie value",
499 __func__);
500 return -EINVAL;
501 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530502
503 /* wait until remain on channel ready event received
Jeff Johnson295189b2012-06-20 16:38:30 -0700504 * for already issued remain on channel request */
505 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
506 msecs_to_jiffies(WAIT_REM_CHAN_READY));
507 if (!status)
508 {
509 hddLog( LOGE,
510 "%s: timeout waiting for remain on channel ready indication",
511 __func__);
512 }
513 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
514 /* Issue abort remain on chan request to sme.
515 * The remain on channel callback will make sure the remain_on_chan
516 * expired event is sent.
517 */
518 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700519 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
520 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700521 )
522 {
523 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700524 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
525 sessionId );
526 }
527 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
528 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
529 )
530 {
531 WLANSAP_CancelRemainOnChannel(
532 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
533 }
534 else
535 {
536 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
537 __func__, pAdapter->device_mode);
538 return -EIO;
539 }
540 wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
541 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
542 return 0;
543}
544
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800545#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
546int wlan_hdd_action( struct wiphy *wiphy, struct wireless_dev *wdev,
547 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700548#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800549 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700550 bool channel_type_valid,
551#endif
552 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800553 const u8 *buf, size_t len, bool no_cck,
554 bool dont_wait_for_ack, u64 *cookie )
555#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700556int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
557 struct ieee80211_channel *chan, bool offchan,
558 enum nl80211_channel_type channel_type,
559 bool channel_type_valid, unsigned int wait,
560 const u8 *buf, size_t len, bool no_cck,
561 bool dont_wait_for_ack, u64 *cookie )
562#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
563int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
564 struct ieee80211_channel *chan, bool offchan,
565 enum nl80211_channel_type channel_type,
566 bool channel_type_valid, unsigned int wait,
567 const u8 *buf, size_t len, u64 *cookie )
568#else
569int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
570 struct ieee80211_channel *chan,
571 enum nl80211_channel_type channel_type,
572 bool channel_type_valid,
573 const u8 *buf, size_t len, u64 *cookie )
574#endif //LINUX_VERSION_CODE
575{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800576#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
577 struct net_device *dev = wdev->netdev;
578#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700579 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
580 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530581 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700582 tANI_U16 extendedWait = 0;
583 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
584 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
585 tActionFrmType actionFrmType;
586 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530587 int status;
Chet Lanctot186b5732013-03-18 10:26:30 -0700588#ifdef WLAN_FEATURE_11W
589 tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit
590#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700591
Jeff Johnson295189b2012-06-20 16:38:30 -0700592#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
593 hdd_adapter_t *goAdapter;
594#endif
595
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530596 status = wlan_hdd_validate_context(pHddCtx);
597
598 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800599 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530600 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
601 "%s: HDD context is not valid", __func__);
602 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800603 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530604
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700605#ifdef WLAN_FEATURE_P2P_DEBUG
606 if ((type == SIR_MAC_MGMT_FRAME) &&
607 (subType == SIR_MAC_MGMT_ACTION) &&
608 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
609 {
610 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800611 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700612 {
613 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
614 actionFrmType);
615 }
616 else
617 {
618 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
619 p2p_action_frame_type[actionFrmType]);
620 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
621 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
622 {
623 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
624 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800625 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700626 }
627 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
628 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
629 {
630 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
631 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
632 " completed state");
633 }
634 }
635 }
636#endif
637
Jeff Johnsone7245742012-09-05 17:12:55 -0700638#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
639 noack = dont_wait_for_ack;
640#endif
641
642 //If the wait is coming as 0 with off channel set
643 //then set the wait to 200 ms
644 if (offchan && !wait)
645 wait = ACTION_FRAME_DEFAULT_WAIT;
646
Jeff Johnson295189b2012-06-20 16:38:30 -0700647 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
648 __func__,pAdapter->device_mode);
649
650 //Call sme API to send out a action frame.
651 // OR can we send it directly through data path??
652 // After tx completion send tx status back.
653 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
654 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
655 )
656 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700657 if (type == SIR_MAC_MGMT_FRAME)
658 {
659 if (subType == SIR_MAC_MGMT_PROBE_RSP)
660 {
661 /* Drop Probe response recieved from supplicant, as for GO and
662 SAP PE itself sends probe response
663 */
664 goto err_rem_channel;
665 }
666 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
667 (subType == SIR_MAC_MGMT_DEAUTH))
668 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700669 /* During EAP failure or P2P Group Remove supplicant
670 * is sending del_station command to driver. From
671 * del_station function, Driver will send deauth frame to
672 * p2p client. No need to send disassoc frame from here.
673 * so Drop the frame here and send tx indication back to
674 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700675 */
676 tANI_U8 dstMac[ETH_ALEN] = {0};
677 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700678 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700679 "%s: Deauth/Disassoc received for STA:"
Jeff Johnsone7245742012-09-05 17:12:55 -0700680 "%02x:%02x:%02x:%02x:%02x:%02x",
681 __func__,
682 dstMac[0], dstMac[1], dstMac[2],
Jeff Johnson295189b2012-06-20 16:38:30 -0700683 dstMac[3], dstMac[4], dstMac[5]);
Jeff Johnson295189b2012-06-20 16:38:30 -0700684 goto err_rem_channel;
685 }
686 }
687 }
688
689 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800690 {
691 if ( !noack )
692 {
693 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
694 __func__);
695 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
696 }
697 else
698 {
699 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
700 __func__);
701 return -EBUSY;
702 }
703 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700704
705 hddLog( LOG1, "Action frame tx request");
706
707#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
708 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
709
710 //If GO adapter exists and operating on same frequency
711 //then we will not request remain on channel
712 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
713 == goAdapter->sessionCtx.ap.operatingChannel ) )
714 {
715 goto send_frame;
716 }
717#endif
718
719#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
720 if( offchan && wait)
721 {
722 int status;
723
724 // In case of P2P Client mode if we are already
725 // on the same channel then send the frame directly
726
727 if((cfgState->remain_on_chan_ctx != NULL) &&
728 (cfgState->current_freq == chan->center_freq)
729 )
730 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700731 hddLog(LOG1,"action frame: extending the wait time\n");
732 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700733 goto send_frame;
734 }
Kiet Lam62111f22013-10-08 21:43:54 +0530735 remain_on_channel:
Jeff Johnson295189b2012-06-20 16:38:30 -0700736 INIT_COMPLETION(pAdapter->offchannel_tx_event);
737
738 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700739 chan,
740#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
741 channel_type,
742#endif
743 wait, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700744 OFF_CHANNEL_ACTION_TX);
745
746 if(0 != status)
747 {
748 if( (-EBUSY == status) &&
749 (cfgState->current_freq == chan->center_freq) )
750 {
751 goto send_frame;
752 }
753 goto err_rem_channel;
754 }
Madan Mohan Koyyalamudi87673f62013-09-27 02:39:27 +0530755 /* This will extend timer in LIM when sending Any action frame
756 * It will cover remain on channel timer till next action frame
757 * in rx direction.
758 */
759 extendedWait = (tANI_U16)wait;
Jeff Johnson295189b2012-06-20 16:38:30 -0700760 /* Wait for driver to be ready on the requested channel */
761 status = wait_for_completion_interruptible_timeout(
762 &pAdapter->offchannel_tx_event,
763 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
764 if(!status)
765 {
766 hddLog( LOGE, "Not able to complete remain on channel request"
767 " within timeout period");
768 goto err_rem_channel;
769 }
770 }
771 else if ( offchan )
772 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700773 /* Check before sending action frame
774 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -0700775 if(NULL == cfgState->remain_on_chan_ctx)
776 {
777 goto err_rem_channel;
778 }
779 }
780 send_frame:
781#endif
782
Jeff Johnsone7245742012-09-05 17:12:55 -0700783 if(!noack)
784 {
785 cfgState->buf = vos_mem_malloc( len ); //buf;
786 if( cfgState->buf == NULL )
787 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -0700788
Jeff Johnsone7245742012-09-05 17:12:55 -0700789 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -0700790
Jeff Johnsone7245742012-09-05 17:12:55 -0700791 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700792
793#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700794 if( cfgState->remain_on_chan_ctx )
795 {
796 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
797 *cookie = cfgState->action_cookie;
798 }
799 else
800 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700801#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700802 *cookie = (tANI_U32) cfgState->buf;
803 cfgState->action_cookie = *cookie;
Kiet Lam62111f22013-10-08 21:43:54 +0530804 /*There is race between expiration of remain on channel
805 in driver and also sending an action frame in wlan_hdd_action.
806 As the remain on chan context is NULL here , which means
807 LIM remain on channel timer expired and
808 wlan_hdd_remain_on_channel_callback has cleared
809 cfgState->remain_on_chan_ctx to NULL so let's
810 do a fresh remain on channel.
811 */
812 goto remain_on_channel;
Jeff Johnson295189b2012-06-20 16:38:30 -0700813#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -0700814 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700815#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700816 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700817
818 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700819 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
820 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700821 )
822 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700823 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800824
Jeff Johnsone7245742012-09-05 17:12:55 -0700825 if ((type == SIR_MAC_MGMT_FRAME) &&
826 (subType == SIR_MAC_MGMT_ACTION) &&
827 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -0700828 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700829 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
830 hddLog(LOG1, "Tx Action Frame %u \n", actionFrmType);
831 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -0700832 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700833 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
834 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING \n", __func__);
835 }
836 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
837 {
838 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
839 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700840 }
841 }
Chet Lanctot186b5732013-03-18 10:26:30 -0700842#ifdef WLAN_FEATURE_11W
843 if ((type == SIR_MAC_MGMT_FRAME) &&
844 (subType == SIR_MAC_MGMT_ACTION) &&
845 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME))
846 {
847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
848 "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query");
849 // Since this is an SA Query Action Frame, we have to protect it
850 WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]);
851 }
852#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700853 if (eHAL_STATUS_SUCCESS !=
854 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Jeff Johnsone7245742012-09-05 17:12:55 -0700855 sessionId, buf, len, extendedWait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -0700856 {
857 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
858 "%s: sme_sendAction returned fail", __func__);
859 goto err;
860 }
861 }
862 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
863 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
864 )
865 {
Jeff Johnson43971f52012-07-17 12:26:56 -0700866 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -0700867 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -0700868 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -0700869 {
870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
871 "%s: WLANSAP_SendAction returned fail", __func__);
872 goto err;
873 }
874 }
875
876 return 0;
877err:
Jeff Johnsone7245742012-09-05 17:12:55 -0700878 if(!noack)
879 {
880 hdd_sendActionCnf( pAdapter, FALSE );
881 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700882 return 0;
883err_rem_channel:
884 *cookie = (tANI_U32)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800885 cfg80211_mgmt_tx_status(
886#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
887 pAdapter->dev->ieee80211_ptr,
888#else
889 pAdapter->dev,
890#endif
891 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -0700892 return 0;
893}
894
895#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800896#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
897int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
898 struct wireless_dev *wdev,
899 u64 cookie)
900{
901 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
902}
903#else
904int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -0700905 struct net_device *dev,
906 u64 cookie)
907{
908 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
909}
910#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800911#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700912
913void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
914{
915 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
916
Jeff Johnsone7245742012-09-05 17:12:55 -0700917 cfgState->actionFrmState = HDD_IDLE;
918
Jeff Johnson295189b2012-06-20 16:38:30 -0700919 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
920 if( NULL == cfgState->buf )
921 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700922 return;
923 }
924
925 /* If skb is NULL it means this packet was received on CFG80211 interface
926 * else it was received on Monitor interface */
927 if( cfgState->skb == NULL )
928 {
929 /*
930 * buf is the same pointer it passed us to send. Since we are sending
931 * it through control path, we use different buffers.
932 * In case of mac80211, they just push it to the skb and pass the same
933 * data while sending tx ack status.
934 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800935 cfg80211_mgmt_tx_status(
936#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
937 pAdapter->dev->ieee80211_ptr,
938#else
939 pAdapter->dev,
940#endif
941 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700942 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
943 vos_mem_free( cfgState->buf );
944 cfgState->buf = NULL;
945 }
946 else
947 {
948 hdd_adapter_t* pMonAdapter =
949 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
950 if( pMonAdapter == NULL )
951 {
952 hddLog( LOGE, "Not able to get Monitor Adapter");
953 cfgState->skb = NULL;
954 vos_mem_free( cfgState->buf );
955 cfgState->buf = NULL;
956 complete(&pAdapter->tx_action_cnf_event);
957 return;
958 }
959 /* Send TX completion feedback over monitor interface. */
960 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
961 cfgState->skb = NULL;
962 vos_mem_free( cfgState->buf );
963 cfgState->buf = NULL;
964 /* Look for the next Mgmt packet to TX */
965 hdd_mon_tx_mgmt_pkt(pAdapter);
966 }
967 complete(&pAdapter->tx_action_cnf_event);
968}
969
970/**
971 * hdd_setP2pNoa
972 *
973 *FUNCTION:
974 * This function is called from hdd_hostapd_ioctl function when Driver
975 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
976 *
977 *LOGIC:
978 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
979 *
980 *ASSUMPTIONS:
981 *
982 *
983 *NOTE:
984 *
985 * @param dev Pointer to net device structure
986 * @param command Pointer to command
987 *
988 * @return Status
989 */
990
991int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
992{
993 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
994 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
995 VOS_STATUS status = VOS_STATUS_SUCCESS;
996 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -0800997 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -0700998 char *param;
999
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001000 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001001 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001002 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001003 param++;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001004 sscanf(param, "%d %d %d", &count, &start_time, &duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1006 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d \n",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001007 __func__, count, start_time, duration);
1008 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001009 /* PS Selection
1010 * Periodic NoA (2)
1011 * Single NOA (4)
1012 */
1013 NoA.opp_ps = 0;
1014 NoA.ctWindow = 0;
1015 if (count == 1)
1016 {
1017 NoA.duration = 0;
1018 NoA.single_noa_duration = duration;
1019 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1020 }
1021 else
1022 {
1023 NoA.duration = duration;
1024 NoA.single_noa_duration = 0;
1025 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1026 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001027 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001028 NoA.count = count;
1029 NoA.sessionid = pAdapter->sessionId;
1030
1031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1032 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1033 "interval %d count %d single noa duration %d "
1034 "PsSelection %x \n", __func__, NoA.opp_ps,
1035 NoA.ctWindow, NoA.duration, NoA.interval,
1036 NoA.count, NoA.single_noa_duration,
1037 NoA.psSelection);
1038
1039 sme_p2pSetPs(hHal, &NoA);
1040 return status;
1041}
1042
1043/**
1044 * hdd_setP2pOpps
1045 *
1046 *FUNCTION:
1047 * This function is called from hdd_hostapd_ioctl function when Driver
1048 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1049 *
1050 *LOGIC:
1051 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1052 *
1053 *ASSUMPTIONS:
1054 *
1055 *
1056 *NOTE:
1057 *
1058 * @param dev Pointer to net device structure
1059 * @param command Pointer to command
1060 *
1061 * @return Status
1062 */
1063
1064int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1065{
1066 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1067 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1068 VOS_STATUS status = VOS_STATUS_SUCCESS;
1069 tP2pPsConfig NoA;
1070 char *param;
1071 int legacy_ps, opp_ps, ctwindow;
1072
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001073 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001074 if (param == NULL)
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001075 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001076 param++;
1077 sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1078 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1079 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1080 __func__, legacy_ps, opp_ps, ctwindow);
1081
1082 /* PS Selection
1083 * Opportunistic Power Save (1)
1084 */
1085
1086 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1087 * When user want to set ctWindow during that time other parameters
1088 * values are coming from wpa_supplicant as -1.
1089 * Example : User want to set ctWindow with 30 then wpa_cli command :
1090 * P2P_SET ctwindow 30
1091 * Command Received at hdd_hostapd_ioctl is as below:
1092 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
1093 */
1094 if (ctwindow != -1)
1095 {
1096
1097 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1098 "Opportunistic Power Save is %s \n",
1099 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1100
1101 if (ctwindow != pAdapter->ctw)
1102 {
1103 pAdapter->ctw = ctwindow;
1104
1105 if(pAdapter->ops)
1106 {
1107 NoA.opp_ps = pAdapter->ops;
1108 NoA.ctWindow = pAdapter->ctw;
1109 NoA.duration = 0;
1110 NoA.single_noa_duration = 0;
1111 NoA.interval = 0;
1112 NoA.count = 0;
1113 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1114 NoA.sessionid = pAdapter->sessionId;
1115
1116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1117 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1118 "interval %d count %d single noa duration %d "
1119 "PsSelection %x \n", __func__, NoA.opp_ps,
1120 NoA.ctWindow, NoA.duration, NoA.interval,
1121 NoA.count, NoA.single_noa_duration,
1122 NoA.psSelection);
1123
1124 sme_p2pSetPs(hHal, &NoA);
1125 }
1126 return 0;
1127 }
1128 }
1129
1130 if (opp_ps != -1)
1131 {
1132 pAdapter->ops = opp_ps;
1133
1134 if ((opp_ps != -1) && (pAdapter->ctw))
1135 {
1136 NoA.opp_ps = opp_ps;
1137 NoA.ctWindow = pAdapter->ctw;
1138 NoA.duration = 0;
1139 NoA.single_noa_duration = 0;
1140 NoA.interval = 0;
1141 NoA.count = 0;
1142 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1143 NoA.sessionid = pAdapter->sessionId;
1144
1145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1146 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1147 "interval %d count %d single noa duration %d "
1148 "PsSelection %x \n", __func__, NoA.opp_ps,
1149 NoA.ctWindow, NoA.duration, NoA.interval,
1150 NoA.count, NoA.single_noa_duration,
1151 NoA.psSelection);
1152
1153 sme_p2pSetPs(hHal, &NoA);
1154 }
1155 }
1156 return status;
1157}
1158
1159int hdd_setP2pPs( struct net_device *dev, void *msgData )
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 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1166
1167 NoA.opp_ps = pappNoA->opp_ps;
1168 NoA.ctWindow = pappNoA->ctWindow;
1169 NoA.duration = pappNoA->duration;
1170 NoA.interval = pappNoA->interval;
1171 NoA.count = pappNoA->count;
1172 NoA.single_noa_duration = pappNoA->single_noa_duration;
1173 NoA.psSelection = pappNoA->psSelection;
1174 NoA.sessionid = pAdapter->sessionId;
1175
1176 sme_p2pSetPs(hHal, &NoA);
1177 return status;
1178}
Jeff Johnson295189b2012-06-20 16:38:30 -07001179
1180static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1181{
1182 tANI_U8 sessionType;
1183
1184 switch( type )
1185 {
1186 case NL80211_IFTYPE_AP:
1187 sessionType = WLAN_HDD_SOFTAP;
1188 break;
1189 case NL80211_IFTYPE_P2P_GO:
1190 sessionType = WLAN_HDD_P2P_GO;
1191 break;
1192 case NL80211_IFTYPE_P2P_CLIENT:
1193 sessionType = WLAN_HDD_P2P_CLIENT;
1194 break;
1195 case NL80211_IFTYPE_STATION:
1196 sessionType = WLAN_HDD_INFRA_STATION;
1197 break;
1198 case NL80211_IFTYPE_MONITOR:
1199 sessionType = WLAN_HDD_MONITOR;
1200 break;
1201 default:
1202 sessionType = WLAN_HDD_INFRA_STATION;
1203 break;
1204 }
1205
1206 return sessionType;
1207}
1208
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001209#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1210struct wireless_dev* wlan_hdd_add_virtual_intf(
1211 struct wiphy *wiphy, const char *name,
1212 enum nl80211_iftype type,
1213 u32 *flags, struct vif_params *params )
1214#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1215struct wireless_dev* wlan_hdd_add_virtual_intf(
1216 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1217 u32 *flags, struct vif_params *params )
1218#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001219struct net_device* wlan_hdd_add_virtual_intf(
1220 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1221 u32 *flags, struct vif_params *params )
1222#else
1223int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1224 enum nl80211_iftype type,
1225 u32 *flags, struct vif_params *params )
1226#endif
1227{
1228 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1229 hdd_adapter_t* pAdapter = NULL;
1230
1231 ENTER();
1232
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001233 if(hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
1234 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001235 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001236 "interfaces of same type are not supported currently.",__func__, type);
Jeff Johnsond13512a2012-07-17 11:42:19 -07001237 return NULL;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001238 }
1239
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001240 if (pHddCtx->isLogpInProgress)
1241 {
1242 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1243 "%s:LOGP in Progress. Ignore!!!", __func__);
1244#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1245 return NULL;
1246#else
1247 return -EAGAIN;
1248#endif
1249 }
Kiet Lam04e26912013-10-18 20:13:38 +05301250 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1251 ((NL80211_IFTYPE_P2P_GO == type) ||
1252 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001253 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001254 /* Generate the P2P Interface Address. this address must be
1255 * different from the P2P Device Address.
1256 */
1257 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1258 p2pDeviceAddress.bytes[4] ^= 0x80;
1259 pAdapter = hdd_open_adapter( pHddCtx,
1260 wlan_hdd_get_session_type(type),
1261 name, p2pDeviceAddress.bytes,
1262 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001263 }
1264 else
1265 {
1266 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1267 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1268 }
1269
1270 if( NULL == pAdapter)
1271 {
1272 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1273#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1274 return NULL;
1275#else
1276 return -EINVAL;
1277#endif
1278 }
1279 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001280#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1281 return pAdapter->dev->ieee80211_ptr;
1282#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001283 return pAdapter->dev;
1284#else
1285 return 0;
1286#endif
1287}
1288
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001289#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1290int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1291#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001292int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001293#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001294{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001295#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1296 struct net_device *dev = wdev->netdev;
1297#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301298 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
1299 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1300 int status;
1301 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001302
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301303 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1304 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001305
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301306 status = wlan_hdd_validate_context(pHddCtx);
1307
1308 if (0 != status)
1309 {
1310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1311 "%s: HDD context is not valid", __func__);
1312 return status;
1313 }
1314
1315 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001316 pVirtAdapter->macAddressCurrent.bytes );
1317
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301318 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1319 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1320 EXIT();
1321 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001322}
1323
1324void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001325 tANI_U32 nFrameLength,
1326 tANI_U8* pbFrames,
Jeff Johnson295189b2012-06-20 16:38:30 -07001327 tANI_U8 frameType )
1328{
1329 //Indicate a Frame over Monitor Intf.
1330 int rxstat;
1331 struct sk_buff *skb = NULL;
1332 int needed_headroom = 0;
1333 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1334 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001335#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001336#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1337 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1338#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001339#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001340 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1341
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001342 if (NULL == pbFrames)
1343 {
1344 hddLog(LOGE, FL("NULL frame pointer"));
1345 return;
1346 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001347
1348 /* room for the radiotap header based on driver features
1349 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1350 * RX flags.
1351 * */
1352 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1353
1354 //alloc skb here
1355 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1356 if (unlikely(NULL == skb))
1357 {
1358 hddLog( LOGW, FL("Unable to allocate skb"));
1359 return;
1360 }
1361 skb_reserve(skb, VPKT_SIZE_BUFFER);
1362 if (unlikely(skb_headroom(skb) < nFrameLength))
1363 {
1364 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1365 "HDD [%d]: Insufficient headroom, "
1366 "head[%p], data[%p], req[%d]",
1367 __LINE__, skb->head, skb->data, nFrameLength);
1368 kfree_skb(skb);
1369 return ;
1370 }
1371 // actually push the data
1372 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1373 /* prepend radiotap information */
1374 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1375 {
1376 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1377 //free skb
1378 kfree_skb(skb);
1379 return ;
1380 }
1381
1382 skb_reset_mac_header( skb );
1383 skb->dev = pMonAdapter->dev;
1384 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001385 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001386#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001387#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001388 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001389#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001390#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001391 rxstat = netif_rx_ni(skb);
1392 if( NET_RX_SUCCESS == rxstat )
1393 {
1394 hddLog( LOG1, FL("Success"));
1395 }
1396 else
1397 hddLog( LOGE, FL("Failed %d"), rxstat);
1398
1399 return ;
1400}
1401
1402void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
1403 tANI_U32 nFrameLength,
1404 tANI_U8* pbFrames,
1405 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301406 tANI_U32 rxChan,
1407 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001408{
1409 tANI_U16 freq;
Jeff Johnsone7245742012-09-05 17:12:55 -07001410 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001411 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001412 tActionFrmType actionFrmType;
1413 hdd_cfg80211_state_t *cfgState = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001414
1415 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d\n",
1416 __func__, frameType, nFrameLength);
1417
1418 if (NULL == pAdapter)
1419 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001420 hddLog(LOGE, FL("pAdapter is NULL"));
1421 return;
1422 }
1423
1424 if (0 == nFrameLength)
1425 {
1426 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
1427 return;
1428 }
1429
1430 if (NULL == pbFrames)
1431 {
1432 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001433 return;
1434 }
1435
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001436 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1437 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1438
1439 /* Get pAdapter from Destination mac address of the frame */
1440 if ((type == SIR_MAC_MGMT_FRAME) &&
1441 (subType != SIR_MAC_MGMT_PROBE_REQ))
1442 {
1443 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1444 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1445 if (NULL == pAdapter)
1446 {
1447 /* Under assumtion that we don't receive any action frame
1448 * with BCST as destination we dropping action frame
1449 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001450 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1451 MAC_ADDRESS_STR ,
1452 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1453 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
1454 " subType = %d \n",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001455 return;
1456 }
1457 }
1458
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001459
Jeff Johnson295189b2012-06-20 16:38:30 -07001460 if (NULL == pAdapter->dev)
1461 {
1462 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1463 return;
1464 }
1465
1466 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1467 {
1468 hddLog( LOGE, FL("pAdapter has invalid magic"));
1469 return;
1470 }
1471
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001472 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1473 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001474 {
1475 hdd_adapter_t *pMonAdapter =
1476 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1477
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001478 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001479 {
1480 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1481 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1482 pbFrames, frameType);
1483 return;
1484 }
1485 }
1486
1487 //Channel indicated may be wrong. TODO
1488 //Indicate an action frame.
1489 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1490 {
1491 freq = ieee80211_channel_to_frequency( rxChan,
1492 IEEE80211_BAND_2GHZ);
1493 }
1494 else
1495 {
1496 freq = ieee80211_channel_to_frequency( rxChan,
1497 IEEE80211_BAND_5GHZ);
1498 }
1499
Jeff Johnsone7245742012-09-05 17:12:55 -07001500 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1501
1502 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001503 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001504 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001505 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1506 {
1507 // public action frame
1508 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001509 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 -08001510 // P2P action frames
1511 {
1512 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
1513 hddLog(LOG1, "Rx Action Frame %u \n", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001514#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001515 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1516 {
1517 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1518 actionFrmType);
1519 }
1520 else
1521 {
1522 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1523 p2p_action_frame_type[actionFrmType]);
1524 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1525 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1526 {
1527 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1528 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001529 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001530 }
1531 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1532 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1533 {
1534 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001535 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1536 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001537 }
1538 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1539 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1540 {
1541 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1542 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1543 " completed state Autonomous GO formation");
1544 }
1545 }
1546#endif
1547
1548 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
1549 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
1550 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
1551 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
1552 {
1553 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
1554 __func__);
1555 hdd_sendActionCnf(pAdapter, TRUE);
1556 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001557 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001558#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001559 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 -07001560 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001561 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
1562#ifdef WLAN_FEATURE_TDLS_DEBUG
1563 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
1564 MAC_ADDR_ARRAY(mac),rxRssi);
1565#endif
1566 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
1567 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001568 }
1569#endif
1570 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001571#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001572 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
1573 {
1574 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
1575 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
1576 {
1577 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
1578 actionFrmType);
1579 }
1580 else
1581 {
1582 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
1583 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001584 }
1585 }
1586#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07001587 }
1588
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 //Indicate Frame Over Normal Interface
1590 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
1591
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001592#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1593 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
1594 pbFrames, nFrameLength,
1595 GFP_ATOMIC );
1596#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07001597 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
1598 pbFrames, nFrameLength,
1599 GFP_ATOMIC );
1600#else
1601 cfg80211_rx_mgmt( pAdapter->dev, freq,
1602 pbFrames, nFrameLength,
1603 GFP_ATOMIC );
1604#endif //LINUX_VERSION_CODE
1605}
1606
1607/*
1608 * ieee80211_add_rx_radiotap_header - add radiotap header
1609 */
1610static int hdd_wlan_add_rx_radiotap_hdr (
1611 struct sk_buff *skb, int rtap_len, int flag )
1612{
1613 u8 rtap_temp[20] = {0};
1614 struct ieee80211_radiotap_header *rthdr;
1615 unsigned char *pos;
1616 u16 rx_flags = 0;
1617
1618 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
1619
1620 /* radiotap header, set always present flags */
1621 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
1622 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
1623 rthdr->it_len = cpu_to_le16(rtap_len);
1624
1625 pos = (unsigned char *) (rthdr + 1);
1626
1627 /* the order of the following fields is important */
1628
1629 /* IEEE80211_RADIOTAP_FLAGS */
1630 *pos = 0;
1631 pos++;
1632
1633 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
1634 /* ensure 2 byte alignment for the 2 byte field as required */
1635 if ((pos - (u8 *)rthdr) & 1)
1636 pos++;
1637 put_unaligned_le16(rx_flags, pos);
1638 pos += 2;
1639
1640 // actually push the data
1641 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
1642
1643 return 0;
1644}
1645
1646static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
1647 hdd_cfg80211_state_t* cfgState,
1648 tANI_BOOLEAN actionSendSuccess )
1649{
1650 struct ieee80211_radiotap_header *rthdr;
1651 unsigned char *pos;
1652 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001653#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001654#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1655 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
1656#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001657#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001658
1659 /* 2 Byte for TX flags and 1 Byte for Retry count */
1660 u32 rtHdrLen = sizeof(*rthdr) + 3;
1661
1662 u8 *data;
1663
1664 /* We have to return skb with Data starting with MAC header. We have
1665 * copied SKB data starting with MAC header to cfgState->buf. We will pull
1666 * entire skb->len from skb and then we will push cfgState->buf to skb
1667 * */
1668 if( NULL == skb_pull(skb, skb->len) )
1669 {
1670 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
1671 kfree_skb(cfgState->skb);
1672 return;
1673 }
1674
1675 data = skb_push( skb, cfgState->len );
1676
1677 if (data == NULL)
1678 {
1679 hddLog( LOGE, FL("Not Able to Push %d byte to skb"), cfgState->len);
1680 kfree_skb( cfgState->skb );
1681 return;
1682 }
1683
1684 memcpy( data, cfgState->buf, cfgState->len );
1685
1686 /* send frame to monitor interfaces now */
1687 if( skb_headroom(skb) < rtHdrLen )
1688 {
1689 hddLog( LOGE, FL("No headroom for rtap header"));
1690 kfree_skb(cfgState->skb);
1691 return;
1692 }
1693
1694 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
1695
1696 memset( rthdr, 0, rtHdrLen );
1697 rthdr->it_len = cpu_to_le16( rtHdrLen );
1698 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
1699 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
1700 );
1701
1702 pos = (unsigned char *)( rthdr+1 );
1703
1704 // Fill TX flags
1705 *pos = actionSendSuccess;
1706 pos += 2;
1707
1708 // Fill retry count
1709 *pos = 0;
1710 pos++;
1711
1712 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001713 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07001714 skb->pkt_type = PACKET_OTHERHOST;
1715 skb->protocol = htons(ETH_P_802_2);
1716 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001717#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001718#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001719 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001720#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001721#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001722 if (in_interrupt())
1723 netif_rx( skb );
1724 else
1725 netif_rx_ni( skb );
1726
1727 /* Enable Queues which we have disabled earlier */
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05301728 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07001729
1730}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05301731