blob: ce3d8ed154a07bc4bb7ba27b9d1afb1c960071c2 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
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.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**========================================================================
29
30 \file wlan_hdd_p2p.c
31
32 \brief WLAN Host Device Driver implementation for P2P commands interface
33
34 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
35
36 Qualcomm Confidential and Proprietary.
37
38 ========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070039
40#include <wlan_hdd_includes.h>
41#include <wlan_hdd_hostapd.h>
42#include <net/cfg80211.h>
43#include "sme_Api.h"
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -070044#include "sme_QosApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070045#include "wlan_hdd_p2p.h"
46#include "sapApi.h"
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053047#include "wlan_hdd_main.h"
Daram Sudha1f7e0e92013-12-17 07:52:31 +053048#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070049#include <linux/netdevice.h>
50#include <linux/skbuff.h>
51#include <linux/etherdevice.h>
52#include <net/ieee80211_radiotap.h>
Hoonki Lee1090c6a2013-01-16 17:40:54 -080053#ifdef FEATURE_WLAN_TDLS
54#include "wlan_hdd_tdls.h"
55#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053056#include "wlan_hdd_trace.h"
57#include "vos_types.h"
58#include "vos_trace.h"
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080059//Ms to Micro Sec
60#define MS_TO_MUS(x) ((x)*1000);
61
Daram Sudha1f7e0e92013-12-17 07:52:31 +053062tANI_U8* hdd_getActionString( tANI_U16 MsgType )
63{
64 switch (MsgType)
65 {
66 CASE_RETURN_STRING(SIR_MAC_ACTION_SPECTRUM_MGMT);
67 CASE_RETURN_STRING(SIR_MAC_ACTION_QOS_MGMT);
68 CASE_RETURN_STRING(SIR_MAC_ACTION_DLP);
69 CASE_RETURN_STRING(SIR_MAC_ACTION_BLKACK);
70 CASE_RETURN_STRING(SIR_MAC_ACTION_PUBLIC_USAGE);
71 CASE_RETURN_STRING(SIR_MAC_ACTION_RRM);
72 CASE_RETURN_STRING(SIR_MAC_ACTION_FAST_BSS_TRNST);
73 CASE_RETURN_STRING(SIR_MAC_ACTION_HT);
74 CASE_RETURN_STRING(SIR_MAC_ACTION_SA_QUERY);
75 CASE_RETURN_STRING(SIR_MAC_ACTION_PROT_DUAL_PUB);
76 CASE_RETURN_STRING(SIR_MAC_ACTION_WNM);
77 CASE_RETURN_STRING(SIR_MAC_ACTION_UNPROT_WNM);
78 CASE_RETURN_STRING(SIR_MAC_ACTION_TDLS);
79 CASE_RETURN_STRING(SIR_MAC_ACITON_MESH);
80 CASE_RETURN_STRING(SIR_MAC_ACTION_MULTIHOP);
81 CASE_RETURN_STRING(SIR_MAC_SELF_PROTECTED);
82 CASE_RETURN_STRING(SIR_MAC_ACTION_WME);
83 CASE_RETURN_STRING(SIR_MAC_ACTION_VHT);
84 default:
85 return ("UNKNOWN");
86 }
87}
88
89
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070090#ifdef WLAN_FEATURE_P2P_DEBUG
91#define MAX_P2P_ACTION_FRAME_TYPE 9
92const char *p2p_action_frame_type[]={"GO Negotiation Request",
93 "GO Negotiation Response",
94 "GO Negotiation Confirmation",
95 "P2P Invitation Request",
96 "P2P Invitation Response",
97 "Device Discoverability Request",
98 "Device Discoverability Response",
99 "Provision Discovery Request",
100 "Provision Discovery Response"};
101
102/* We no need to protect this variable since
103 * there is no chance of race to condition
104 * and also not make any complicating the code
105 * just for debugging log
106 */
107tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
108
109#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800110#ifdef WLAN_FEATURE_TDLS_DEBUG
111#define MAX_TDLS_ACTION_FRAME_TYPE 11
112const char *tdls_action_frame_type[] = {"TDLS Setup Request",
113 "TDLS Setup Response",
114 "TDLS Setup Confirm",
115 "TDLS Teardown",
116 "TDLS Peer Traffic Indication",
117 "TDLS Channel Switch Request",
118 "TDLS Channel Switch Response",
119 "TDLS Peer PSM Request",
120 "TDLS Peer PSM Response",
121 "TDLS Peer Traffic Response",
122 "TDLS Discovery Request" };
123#endif
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700124
Jeff Johnson295189b2012-06-20 16:38:30 -0700125extern struct net_device_ops net_ops_struct;
126
127static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
128 int rtap_len, int flag );
129
130static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
131 hdd_cfg80211_state_t* cfgState,
132 tANI_BOOLEAN actionSendSuccess );
133
134static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Rashmi Ramannac7744532013-10-06 16:49:08 +0530135 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -0700136 tANI_U8* pbFrames,
137 tANI_U8 frameType );
vamsi9bd92b72013-12-26 14:11:29 +0530138
139static v_BOOL_t hdd_p2p_is_action_type_rsp( const u8 *buf )
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530140{
vamsi9bd92b72013-12-26 14:11:29 +0530141 tActionFrmType actionFrmType;
142 const u8 *ouiPtr;
143
144 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
145 WLAN_HDD_PUBLIC_ACTION_FRAME ) {
146 return VOS_FALSE;
147 }
148
149 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] !=
150 WLAN_HDD_VENDOR_SPECIFIC_ACTION ) {
151 return VOS_FALSE;
152 }
153
154 ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET];
155
156 if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) {
157 return VOS_FALSE;
158 }
159
160 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] !=
161 WLAN_HDD_WFA_P2P_OUI_TYPE ) {
162 return VOS_FALSE;
163 }
164
Ahmad Kholaife5ec2cd2014-03-19 13:22:04 +0530165 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
vamsi9bd92b72013-12-26 14:11:29 +0530166 if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
167 actionFrmType != WLAN_HDD_GO_NEG_REQ &&
168 actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
169 actionFrmType != WLAN_HDD_PROV_DIS_REQ )
170 return VOS_TRUE;
171 else
172 return VOS_FALSE;
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530173}
Jeff Johnson295189b2012-06-20 16:38:30 -0700174
Jeff Johnson295189b2012-06-20 16:38:30 -0700175eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
176 eHalStatus status )
177{
178 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700179 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
180 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
181
182 if( pRemainChanCtx == NULL )
183 {
184 hddLog( LOGW,
185 "%s: No Rem on channel pending for which Rsp is received", __func__);
186 return eHAL_STATUS_SUCCESS;
187 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530188 hddLog( VOS_TRACE_LEVEL_INFO,
189 "Received ROC rsp (request type %d, channel %d, cookie %llu",
190 pRemainChanCtx->rem_on_chan_request,
191 pRemainChanCtx->chan.center_freq,
192 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700193 cfgState->remain_on_chan_ctx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530194 vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
195 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
196 if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
Jeff Johnson295189b2012-06-20 16:38:30 -0700197 {
198 if( cfgState->buf )
199 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530200 hddLog( LOGP,
Jeff Johnson295189b2012-06-20 16:38:30 -0700201 "%s: We need to receive yet an ack from one of tx packet",
202 __func__);
203 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800204 cfg80211_remain_on_channel_expired(
205#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
206 pRemainChanCtx->dev->ieee80211_ptr,
207#else
208 pRemainChanCtx->dev,
209#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700210 pRemainChanCtx->cookie,
211 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700212#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
213 pRemainChanCtx->chan_type,
214#endif
215 GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -0700216 }
217
Jeff Johnson295189b2012-06-20 16:38:30 -0700218
219 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700220 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
221 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700222 )
223 {
224 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800225 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
226 {
227 sme_DeregisterMgmtFrame(
228 hHal, sessionId,
229 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
230 NULL, 0 );
231 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700232 }
233 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
234 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
235 )
236 {
237 WLANSAP_DeRegisterMgmtFrame(
238 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
239 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
240 NULL, 0 );
241 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530242 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
243 && pRemainChanCtx->action_pkt_buff.frame_length != 0)
244 {
245 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
246 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800247 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800248 pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700249 complete(&pAdapter->cancel_rem_on_chan_var);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530250 pAdapter->is_roc_inprogress = FALSE;
251 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 return eHAL_STATUS_SUCCESS;
253}
254
Gopichand Nakkalaf527dc62012-12-31 16:35:10 -0800255void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700256{
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530258 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700260
Jeff Johnson32d95a32012-09-10 13:15:23 -0700261 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530263 hddLog(VOS_TRACE_LEVEL_INFO,
264 "Cancel Existing ROC (cookie=%llu)",
265 cfgState->remain_on_chan_ctx->cookie);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700266
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530267 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
268 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE)
269 {
270 hddLog( LOG1,
271 "ROC timer cancellation in progress,"
272 " wait for completion");
273 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
274 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
275 if (0 >= status)
276 {
277 hddLog( LOGE,
278 "%s:wait on cancel_rem_on_chan_var failed %d",
279 __func__, status);
280 }
281 return;
282 }
283 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
284
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530285 /* Wait till remain on channel ready indication before issuing cancel
286 * remain on channel request, otherwise if remain on channel not
287 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700288 * will be in unknown state.
289 */
290 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
291 msecs_to_jiffies(WAIT_REM_CHAN_READY));
c_hpothu7f63e882013-10-02 19:13:35 +0530292 if (0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -0700293 {
294 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530295 "%s: timeout waiting for remain on channel ready indication %d",
296 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -0700297 }
298
299 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530300
Jeff Johnson295189b2012-06-20 16:38:30 -0700301 /* Issue abort remain on chan request to sme.
302 * The remain on channel callback will make sure the remain_on_chan
303 * expired event is sent.
304 */
305 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700306 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
307 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 )
309 {
310 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
311 pAdapter->sessionId );
312 }
313 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
314 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
315 )
316 {
317 WLANSAP_CancelRemainOnChannel(
318 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
319 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700320
Jeff Johnson32d95a32012-09-10 13:15:23 -0700321 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700322 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700323
c_hpothu7f63e882013-10-02 19:13:35 +0530324 if (0 >= status)
Jeff Johnson32d95a32012-09-10 13:15:23 -0700325 {
326 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530327 "%s: timeout waiting for cancel remain on channel ready indication %d",
328 __func__, status);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700329 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530330 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700331 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700332}
333
334int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
335{
336 int status = 0;
337 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
338
339 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
340 {
341 //Cancel Existing Remain On Channel
342 //If no action frame is pending
343 if( cfgState->remain_on_chan_ctx != NULL)
344 {
345 //Check whether Action Frame is pending or not
346 if( cfgState->buf == NULL)
347 {
348 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
349 }
350 else
351 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530352 hddLog(VOS_TRACE_LEVEL_DEBUG,
353 "Cannot Cancel Existing Remain on Channel");
Jeff Johnson32d95a32012-09-10 13:15:23 -0700354 status = -EBUSY;
355 }
356 }
357 }
358 return status;
359}
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530360void wlan_hdd_remain_on_chan_timeout(void *data)
361{
362 hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
363 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
364 hdd_cfg80211_state_t *cfgState;
365 if ( NULL == pAdapter )
366 {
367 hddLog( LOGE, FL("pAdapter is NULL !!!"));
368 return;
369 }
370 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
371 pRemainChanCtx = cfgState->remain_on_chan_ctx;
372 if (NULL == pRemainChanCtx)
373 {
374 hddLog( LOGE, FL("No Remain on channel is pending"));
375 return;
376 }
377 if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
378 {
379 hddLog( LOGE, FL("Cancellation already in progress"));
380 return;
381 }
382
383 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
384 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
385 hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
386 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
387 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
388 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
389 )
390 {
391 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
392 pAdapter->sessionId );
393 }
394 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
395 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
396 )
397 {
398 WLANSAP_CancelRemainOnChannel(
399 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
400 }
401 hdd_allow_suspend();
402}
Jeff Johnson32d95a32012-09-10 13:15:23 -0700403
404static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
405 struct net_device *dev,
406 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700407#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700408 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700409#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700410 unsigned int duration, u64 *cookie,
411 rem_on_channel_request_type_t request_type )
412{
413 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
414 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
415 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530416 VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
417 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
418 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
419 hdd_adapter_t *pAdapter_temp;
420 VOS_STATUS status;
421 v_BOOL_t isGoPresent = VOS_FALSE;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700422 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
423 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700424#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530425 hddLog(VOS_TRACE_LEVEL_INFO,
426 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
427 " request type %d, cookie %llu",
428 chan->hw_value, chan->center_freq, channel_type, duration,
429 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700430#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530431 hddLog(VOS_TRACE_LEVEL_INFO,
432 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
433 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
434 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700435#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700436 //Cancel existing remain On Channel if any
437 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700438
Jeff Johnsone7245742012-09-05 17:12:55 -0700439 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700440 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700441 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700442 * channel requets when Load/Unload is in progress*/
Rashmi Ramannab1429032014-04-26 14:59:09 +0530443 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(((hdd_context_t *)pAdapter->pHddCtx))
444 || hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx))
Jeff Johnson295189b2012-06-20 16:38:30 -0700445 {
446 hddLog( LOGE,
Rashmi Ramannab1429032014-04-26 14:59:09 +0530447 "%s: Wlan Load/Unload or Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700448 return -EBUSY;
449 }
450
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700451 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
452 {
453 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
454 "%s:LOGP in Progress. Ignore!!!", __func__);
455 return -EAGAIN;
456 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700457 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
458 if( NULL == pRemainChanCtx )
459 {
460 hddLog(VOS_TRACE_LEVEL_FATAL,
461 "%s: Not able to allocate memory for Channel context",
462 __func__);
463 return -ENOMEM;
464 }
465
466 vos_mem_copy( &pRemainChanCtx->chan, chan,
467 sizeof(struct ieee80211_channel) );
468
Yue Maf49ba872013-08-19 12:04:25 -0700469#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700470 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700471#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700472 pRemainChanCtx->duration = duration;
473 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800474 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700475 pRemainChanCtx->cookie = *cookie;
476 pRemainChanCtx->rem_on_chan_request = request_type;
477 cfgState->remain_on_chan_ctx = pRemainChanCtx;
478 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530479 pRemainChanCtx->action_pkt_buff.freq = 0;
480 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
481 pRemainChanCtx->action_pkt_buff.frame_length = 0;
482 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
483 /* Initialize Remain on chan timer */
484 vos_status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
485 VOS_TIMER_TYPE_SW,
486 wlan_hdd_remain_on_chan_timeout,
487 pAdapter);
488 if (vos_status != VOS_STATUS_SUCCESS)
489 {
490 hddLog(VOS_TRACE_LEVEL_ERROR,
491 "%s: Not able to initalize remain_on_chan timer", __func__);
492 }
493 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
494 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
495 {
496 pAdapter_temp = pAdapterNode->pAdapter;
497 if (WLAN_HDD_P2P_GO == pAdapter_temp->device_mode)
498 {
499 isGoPresent = VOS_TRUE;
500 }
501 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
502 pAdapterNode = pNext;
503 }
504 /* For GO mode , set the duration to a larger value so that host can extend
505 * ROC if back to back action frames are received. Firmware will start SNOA
506 * with this duration value
507 */
508 if (VOS_TRUE == isGoPresent && OFF_CHANNEL_ACTION_TX == request_type)
509 duration = 3 * duration;
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530510
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530511 hdd_prevent_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700512 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
513
514 //call sme API to start remain on channel.
515 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700516 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
517 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700518 )
519 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700520 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700521 //call sme API to start remain on channel.
522 sme_RemainOnChannel(
Rashmi Ramannac7744532013-10-06 16:49:08 +0530523 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
524 chan->hw_value, duration,
525 wlan_hdd_remain_on_channel_callback, pAdapter,
526 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700527
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800528 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
529 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530530 if( eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame(
531 WLAN_HDD_GET_HAL_CTX(pAdapter),
532 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
533 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ))
534 {
535 hddLog(VOS_TRACE_LEVEL_ERROR,
536 "sme_RegisterMgmtFrame returned fail");
537 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800538 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700539
540 }
541 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
542 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
543 )
544 {
545 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700546 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700547 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
548 chan->hw_value, duration,
549 wlan_hdd_remain_on_channel_callback, pAdapter ))
550
551 {
552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
553 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
554 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700555 vos_mem_free (pRemainChanCtx);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530556 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700557 return -EINVAL;
558 }
559
560
Jeff Johnson43971f52012-07-17 12:26:56 -0700561 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700562 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
563 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
564 NULL, 0 ))
565 {
566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
567 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
568 WLANSAP_CancelRemainOnChannel(
569 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530570 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700571 return -EINVAL;
572 }
573
574 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530575
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530576 pAdapter->is_roc_inprogress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700577 return 0;
578
579}
580
581int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800582#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
583 struct wireless_dev *wdev,
584#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700585 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800586#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700587 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700588#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700589 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700590#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700591 unsigned int duration, u64 *cookie )
592{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800593#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
594 struct net_device *dev = wdev->netdev;
595#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530596 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
597
598 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
599 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
600 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Jeff Johnson295189b2012-06-20 16:38:30 -0700601 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700602 chan,
603#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
604 channel_type,
605#endif
606 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700607 REMAIN_ON_CHANNEL_REQUEST);
608}
609
610void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
611{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530612 hdd_cfg80211_state_t *cfgState = NULL;
613 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530614 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530615 if (NULL == pAdapter)
616 {
617 hddLog(LOGE, FL("pAdapter is NULL"));
618 return;
619 }
620 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
621 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530622 hddLog( LOG1, "Ready on chan ind");
623 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
624 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
625 pAdapter->sessionId, pRemainChanCtx->duration));
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 if( pRemainChanCtx != NULL )
627 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530628 //start timer for actual duration
629 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
630 (pRemainChanCtx->duration));
631 if (VOS_STATUS_SUCCESS!=status)
632 {
633 hddLog( LOGE, FL("Remain on Channel timer start failed"));
634 }
635 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700636 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800637 cfg80211_ready_on_channel(
638#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
639 pAdapter->dev->ieee80211_ptr,
640#else
641 pAdapter->dev,
642#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800643 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700644 &pRemainChanCtx->chan,
645#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
646 pRemainChanCtx->chan_type,
647#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700648 pRemainChanCtx->duration, GFP_KERNEL );
649 }
650#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530651 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700652 {
653 complete(&pAdapter->offchannel_tx_event);
654 }
655#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530656 // Check for cached action frame
657 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
658 {
659#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
660 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
661 pRemainChanCtx->action_pkt_buff.freq, 0,
662 pRemainChanCtx->action_pkt_buff.frame_ptr,
663 pRemainChanCtx->action_pkt_buff.frame_length,
664 GFP_ATOMIC );
665#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
666 cfg80211_rx_mgmt( pAdapter->dev,
667 pRemainChanCtx->action_pkt_buff.freq, 0,
668 pRemainChanCtx->action_pkt_buff.frame_ptr,
669 pRemainChanCtx->action_pkt_buff.frame_length,
670 GFP_ATOMIC );
671#else
672 cfg80211_rx_mgmt( pAdapter->dev,
673 pRemainChanCtx->action_pkt_buff.freq,
674 pRemainChanCtx->action_pkt_buff.frame_ptr,
675 pRemainChanCtx->action_pkt_buff.frame_length,
676 GFP_ATOMIC );
677#endif //LINUX_VERSION_CODE
678 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
679 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
680 pRemainChanCtx->action_pkt_buff.frame_length = 0;
681 pRemainChanCtx->action_pkt_buff.freq = 0;
682 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
683 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530684 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
685 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700686 complete(&pAdapter->rem_on_chan_ready_event);
687 }
688 else
689 {
690 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
691 }
692 return;
693}
694
695int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800696#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
697 struct wireless_dev *wdev,
698#else
699 struct net_device *dev,
700#endif
701 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700702{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800703#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
704 struct net_device *dev = wdev->netdev;
705#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700706 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700707 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530708 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530709 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
710 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530711 u64 cookie_dummy;
712 cookie_dummy = cookie << 32;
713 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
714 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
715 pAdapter->sessionId, cookie_dummy));
716 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -0700717
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530718 status = wlan_hdd_validate_context(pHddCtx);
719
720 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700721 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
723 "%s: HDD context is not valid", __func__);
724 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700725 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530726 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
727
Jeff Johnson295189b2012-06-20 16:38:30 -0700728 /* FIXME cancel currently running remain on chan.
729 * Need to check cookie and cancel accordingly
730 */
731 if( (cfgState->remain_on_chan_ctx == NULL) ||
732 (cfgState->remain_on_chan_ctx->cookie != cookie) )
733 {
734 hddLog( LOGE,
735 "%s: No Remain on channel pending with specified cookie value",
736 __func__);
737 return -EINVAL;
738 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530739 if (NULL != cfgState->remain_on_chan_ctx)
740 {
741 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
742 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
743 {
744 hddLog( LOG1,
745 FL("ROC timer cancellation in progress,"
746 " wait for completion"));
747 status = wait_for_completion_interruptible_timeout(
748 &pAdapter->cancel_rem_on_chan_var,
749 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
750 if (0 >= status)
751 {
752 hddLog( LOGE,
753 "%s:wait on cancel_rem_on_chan_var failed %d",
754 __func__, status);
755 }
756 return 0;
757 }
758 else
759 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
760 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530761 /* wait until remain on channel ready event received
Jeff Johnson295189b2012-06-20 16:38:30 -0700762 * for already issued remain on channel request */
763 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
764 msecs_to_jiffies(WAIT_REM_CHAN_READY));
c_hpothu7f63e882013-10-02 19:13:35 +0530765 if (0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -0700766 {
c_hpothu7f63e882013-10-02 19:13:35 +0530767 hddLog( LOGE,
768 "%s: timeout waiting for remain on channel ready indication %d",
769 __func__, status);
Yue Ma4f55ef32014-01-23 16:45:33 -0800770
771 if (pHddCtx->isLogpInProgress)
772 {
773 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
774 "%s: LOGP in Progress. Ignore!!!", __func__);
775 return -EAGAIN;
776 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700777 }
778 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
779 /* Issue abort remain on chan request to sme.
780 * The remain on channel callback will make sure the remain_on_chan
781 * expired event is sent.
782 */
783 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700784 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
785 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700786 )
787 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530788 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700789 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
790 sessionId );
791 }
792 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
793 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
794 )
795 {
796 WLANSAP_CancelRemainOnChannel(
797 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
798 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530799 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700800 {
801 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
802 __func__, pAdapter->device_mode);
803 return -EIO;
804 }
c_hpothu7f63e882013-10-02 19:13:35 +0530805 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700806 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +0530807 if (0 >= status)
808 {
809 hddLog( LOGE,
810 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
811 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530812 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700813 return 0;
814}
815
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800816#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530817int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800818 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700819#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800820 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700821 bool channel_type_valid,
822#endif
823 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800824 const u8 *buf, size_t len, bool no_cck,
825 bool dont_wait_for_ack, u64 *cookie )
826#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530827int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700828 struct ieee80211_channel *chan, bool offchan,
829 enum nl80211_channel_type channel_type,
830 bool channel_type_valid, unsigned int wait,
831 const u8 *buf, size_t len, bool no_cck,
832 bool dont_wait_for_ack, u64 *cookie )
833#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530834int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700835 struct ieee80211_channel *chan, bool offchan,
836 enum nl80211_channel_type channel_type,
837 bool channel_type_valid, unsigned int wait,
838 const u8 *buf, size_t len, u64 *cookie )
839#else
DARAM SUDHA39eede62014-02-12 11:16:40 +0530840int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700841 struct ieee80211_channel *chan,
842 enum nl80211_channel_type channel_type,
843 bool channel_type_valid,
844 const u8 *buf, size_t len, u64 *cookie )
845#endif //LINUX_VERSION_CODE
846{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800847#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
848 struct net_device *dev = wdev->netdev;
849#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700850 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
851 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530852 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530853 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700854 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
855 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
856 tActionFrmType actionFrmType;
857 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530858 int status;
Chet Lanctot186b5732013-03-18 10:26:30 -0700859#ifdef WLAN_FEATURE_11W
860 tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit
861#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700862
Jeff Johnson295189b2012-06-20 16:38:30 -0700863#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
864 hdd_adapter_t *goAdapter;
865#endif
866
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530867 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
868 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
869 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530870 status = wlan_hdd_validate_context(pHddCtx);
871
872 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800873 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
875 "%s: HDD context is not valid", __func__);
876 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800877 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530878
c_hpothu7f63e882013-10-02 19:13:35 +0530879 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
880 __func__, pAdapter->device_mode, type);
881
882
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700883#ifdef WLAN_FEATURE_P2P_DEBUG
884 if ((type == SIR_MAC_MGMT_FRAME) &&
885 (subType == SIR_MAC_MGMT_ACTION) &&
886 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
887 {
888 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800889 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700890 {
891 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
892 actionFrmType);
893 }
894 else
895 {
896 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
897 p2p_action_frame_type[actionFrmType]);
898 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
899 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
900 {
901 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
902 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800903 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700904 }
905 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
906 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
907 {
908 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
909 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
910 " completed state");
911 }
912 }
913 }
914#endif
915
Jeff Johnsone7245742012-09-05 17:12:55 -0700916#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
917 noack = dont_wait_for_ack;
918#endif
919
920 //If the wait is coming as 0 with off channel set
921 //then set the wait to 200 ms
922 if (offchan && !wait)
923 wait = ACTION_FRAME_DEFAULT_WAIT;
924
Jeff Johnson295189b2012-06-20 16:38:30 -0700925 //Call sme API to send out a action frame.
926 // OR can we send it directly through data path??
927 // After tx completion send tx status back.
928 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
929 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
930 )
931 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700932 if (type == SIR_MAC_MGMT_FRAME)
933 {
934 if (subType == SIR_MAC_MGMT_PROBE_RSP)
935 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530936 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -0700937 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530938 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700939 goto err_rem_channel;
940 }
941 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
942 (subType == SIR_MAC_MGMT_DEAUTH))
943 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700944 /* During EAP failure or P2P Group Remove supplicant
945 * is sending del_station command to driver. From
946 * del_station function, Driver will send deauth frame to
947 * p2p client. No need to send disassoc frame from here.
948 * so Drop the frame here and send tx indication back to
949 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700950 */
951 tANI_U8 dstMac[ETH_ALEN] = {0};
952 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700953 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700954 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -0800955 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -0700956 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -0800957 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700958 goto err_rem_channel;
959 }
960 }
961 }
962
963 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800964 {
965 if ( !noack )
966 {
967 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
968 __func__);
969 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
970 }
971 else
972 {
973 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
974 __func__);
975 return -EBUSY;
976 }
977 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700978
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530979 if( subType == SIR_MAC_MGMT_ACTION)
980 {
981 hddLog( LOG1, "Action frame tx request : %s",
982 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
983 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700984
985#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
986 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
987
988 //If GO adapter exists and operating on same frequency
989 //then we will not request remain on channel
990 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
991 == goAdapter->sessionCtx.ap.operatingChannel ) )
992 {
993 goto send_frame;
994 }
995#endif
996
997#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
998 if( offchan && wait)
999 {
1000 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301001 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001002 // In case of P2P Client mode if we are already
1003 // on the same channel then send the frame directly
1004
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301005 if( (cfgState->remain_on_chan_ctx != NULL) &&
1006 (cfgState->current_freq == chan->center_freq)
1007 )
1008 {
1009 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1010 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301011 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301012 vos_timer_stop(
1013 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1014 status = vos_timer_start(
1015 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1016 wait);
1017 if ( status != VOS_STATUS_SUCCESS )
vamsida0e5ab2013-12-26 14:33:27 +05301018 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301019 hddLog( LOGE, "Remain on Channel timer start failed");
1020 }
1021
1022 hddLog(VOS_TRACE_LEVEL_INFO,
1023 "action frame: extending the wait time %u",
1024 wait);
1025 goto send_frame;
1026 }
1027 else
1028 {
1029 if ( TRUE ==
1030 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1031 {
1032 hddLog(VOS_TRACE_LEVEL_INFO,
1033 "action frame tx: waiting for completion of ROC ");
1034
1035 status = wait_for_completion_interruptible_timeout(
1036 &pAdapter->cancel_rem_on_chan_var,
1037 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1038 if (0 >= status)
1039 {
1040 hddLog( LOGE,
1041 "%s:wait on cancel_rem_on_chan_var failed %d",
1042 __func__, status);
1043 }
vamsida0e5ab2013-12-26 14:33:27 +05301044 }
1045 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301046 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301047 hddLog(VOS_TRACE_LEVEL_INFO,
1048 "action frame: Request ROC for wait time %u", wait);
1049
Jeff Johnson295189b2012-06-20 16:38:30 -07001050 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001051 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001052 chan,
1053#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1054 channel_type,
1055#endif
1056 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301057 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001058
1059 if(0 != status)
1060 {
1061 if( (-EBUSY == status) &&
1062 (cfgState->current_freq == chan->center_freq) )
1063 {
1064 goto send_frame;
1065 }
1066 goto err_rem_channel;
1067 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001068 /* Wait for driver to be ready on the requested channel */
1069 status = wait_for_completion_interruptible_timeout(
1070 &pAdapter->offchannel_tx_event,
1071 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301072 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001073 {
c_hpothu7f63e882013-10-02 19:13:35 +05301074 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001075 goto err_rem_channel;
1076 }
1077 }
1078 else if ( offchan )
1079 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001080 /* Check before sending action frame
1081 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 if(NULL == cfgState->remain_on_chan_ctx)
1083 {
1084 goto err_rem_channel;
1085 }
1086 }
1087 send_frame:
1088#endif
1089
Jeff Johnsone7245742012-09-05 17:12:55 -07001090 if(!noack)
1091 {
1092 cfgState->buf = vos_mem_malloc( len ); //buf;
1093 if( cfgState->buf == NULL )
1094 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001095
Jeff Johnsone7245742012-09-05 17:12:55 -07001096 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001097
Jeff Johnsone7245742012-09-05 17:12:55 -07001098 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001099
1100#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001101 if( cfgState->remain_on_chan_ctx )
1102 {
1103 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1104 *cookie = cfgState->action_cookie;
1105 }
1106 else
1107 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001108#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001109 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001110 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001111#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001112 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001113#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301114 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001115
1116 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001117 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1118 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001119 )
1120 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001121 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001122
Jeff Johnsone7245742012-09-05 17:12:55 -07001123 if ((type == SIR_MAC_MGMT_FRAME) &&
1124 (subType == SIR_MAC_MGMT_ACTION) &&
1125 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001126 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001127 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301128 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001129 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001130 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001131 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301132 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001133 }
1134 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1135 {
1136 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301137 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001138 }
1139 }
Chet Lanctot186b5732013-03-18 10:26:30 -07001140#ifdef WLAN_FEATURE_11W
1141 if ((type == SIR_MAC_MGMT_FRAME) &&
1142 (subType == SIR_MAC_MGMT_ACTION) &&
1143 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME))
1144 {
1145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1146 "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query");
1147 // Since this is an SA Query Action Frame, we have to protect it
1148 WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]);
1149 }
1150#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001151 if (eHAL_STATUS_SUCCESS !=
1152 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301153 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001154 {
1155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1156 "%s: sme_sendAction returned fail", __func__);
1157 goto err;
1158 }
1159 }
1160 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1161 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1162 )
1163 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001164 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001165 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001166 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001167 {
1168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1169 "%s: WLANSAP_SendAction returned fail", __func__);
1170 goto err;
1171 }
1172 }
1173
1174 return 0;
1175err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001176 if(!noack)
1177 {
1178 hdd_sendActionCnf( pAdapter, FALSE );
1179 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001180 return 0;
1181err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001182 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001183 cfg80211_mgmt_tx_status(
1184#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1185 pAdapter->dev->ieee80211_ptr,
1186#else
1187 pAdapter->dev,
1188#endif
1189 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001190 return 0;
1191}
1192
1193#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001194#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1195int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1196 struct wireless_dev *wdev,
1197 u64 cookie)
1198{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301199 u64 cookie_dummy;
1200 cookie_dummy = cookie << 32;
1201 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1202 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001203 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1204}
1205#else
1206int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001207 struct net_device *dev,
1208 u64 cookie)
1209{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301210 u64 cookie_dummy;
1211 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1212 cookie_dummy = cookie << 32;
1213 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1214 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1215 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001216 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1217}
1218#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001219#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001220
1221void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1222{
1223 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1224
Jeff Johnsone7245742012-09-05 17:12:55 -07001225 cfgState->actionFrmState = HDD_IDLE;
1226
Jeff Johnson295189b2012-06-20 16:38:30 -07001227 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1228 if( NULL == cfgState->buf )
1229 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001230 return;
1231 }
1232
1233 /* If skb is NULL it means this packet was received on CFG80211 interface
1234 * else it was received on Monitor interface */
1235 if( cfgState->skb == NULL )
1236 {
1237 /*
1238 * buf is the same pointer it passed us to send. Since we are sending
1239 * it through control path, we use different buffers.
1240 * In case of mac80211, they just push it to the skb and pass the same
1241 * data while sending tx ack status.
1242 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001243 cfg80211_mgmt_tx_status(
1244#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1245 pAdapter->dev->ieee80211_ptr,
1246#else
1247 pAdapter->dev,
1248#endif
1249 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001250 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1251 vos_mem_free( cfgState->buf );
1252 cfgState->buf = NULL;
1253 }
1254 else
1255 {
1256 hdd_adapter_t* pMonAdapter =
1257 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1258 if( pMonAdapter == NULL )
1259 {
1260 hddLog( LOGE, "Not able to get Monitor Adapter");
1261 cfgState->skb = NULL;
1262 vos_mem_free( cfgState->buf );
1263 cfgState->buf = NULL;
1264 complete(&pAdapter->tx_action_cnf_event);
1265 return;
1266 }
1267 /* Send TX completion feedback over monitor interface. */
1268 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1269 cfgState->skb = NULL;
1270 vos_mem_free( cfgState->buf );
1271 cfgState->buf = NULL;
1272 /* Look for the next Mgmt packet to TX */
1273 hdd_mon_tx_mgmt_pkt(pAdapter);
1274 }
1275 complete(&pAdapter->tx_action_cnf_event);
1276}
1277
1278/**
1279 * hdd_setP2pNoa
1280 *
1281 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301282 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001283 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1284 *
1285 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301286 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001287 *
1288 *ASSUMPTIONS:
1289 *
1290 *
1291 *NOTE:
1292 *
1293 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301294 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001295 *
1296 * @return Status
1297 */
1298
1299int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1300{
1301 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1302 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1303 VOS_STATUS status = VOS_STATUS_SUCCESS;
1304 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001305 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001306 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001307 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001308
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001309 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001310 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301311 {
1312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1313 "%s: strnchr failed to find delimeter",__func__);
1314 return -EINVAL;
1315 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001316 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001317 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1318 if (ret < 3)
1319 {
1320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1321 "%s: P2P_SET GO NoA: fail to read param "
1322 "count=%d duration=%d interval=%d \n",
1323 __func__, count, start_time, duration);
1324 return -EINVAL;
1325 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001326 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001327 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001328 __func__, count, start_time, duration);
1329 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001330 /* PS Selection
1331 * Periodic NoA (2)
1332 * Single NOA (4)
1333 */
1334 NoA.opp_ps = 0;
1335 NoA.ctWindow = 0;
1336 if (count == 1)
1337 {
1338 NoA.duration = 0;
1339 NoA.single_noa_duration = duration;
1340 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1341 }
1342 else
1343 {
1344 NoA.duration = duration;
1345 NoA.single_noa_duration = 0;
1346 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1347 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001348 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001349 NoA.count = count;
1350 NoA.sessionid = pAdapter->sessionId;
1351
1352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1353 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1354 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001355 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001356 NoA.ctWindow, NoA.duration, NoA.interval,
1357 NoA.count, NoA.single_noa_duration,
1358 NoA.psSelection);
1359
1360 sme_p2pSetPs(hHal, &NoA);
1361 return status;
1362}
1363
1364/**
1365 * hdd_setP2pOpps
1366 *
1367 *FUNCTION:
1368 * This function is called from hdd_hostapd_ioctl function when Driver
1369 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1370 *
1371 *LOGIC:
1372 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1373 *
1374 *ASSUMPTIONS:
1375 *
1376 *
1377 *NOTE:
1378 *
1379 * @param dev Pointer to net device structure
1380 * @param command Pointer to command
1381 *
1382 * @return Status
1383 */
1384
1385int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1386{
1387 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1388 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1389 VOS_STATUS status = VOS_STATUS_SUCCESS;
1390 tP2pPsConfig NoA;
1391 char *param;
1392 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001393 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001394
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001395 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001396 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301397 {
1398 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1399 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001400 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301401 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001402 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001403 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1404 if (ret < 3)
1405 {
1406 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1407 "%s: P2P_SET GO PS: fail to read param "
1408 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1409 __func__, legacy_ps, opp_ps, ctwindow);
1410 return -EINVAL;
1411 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001412 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001413 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001414 __func__, legacy_ps, opp_ps, ctwindow);
1415
1416 /* PS Selection
1417 * Opportunistic Power Save (1)
1418 */
1419
1420 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1421 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301422 * values are coming from wpa_supplicant as -1.
1423 * Example : User want to set ctWindow with 30 then wpa_cli command :
1424 * P2P_SET ctwindow 30
1425 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001426 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301427 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001428 if (ctwindow != -1)
1429 {
1430
1431 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001432 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001433 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1434
1435 if (ctwindow != pAdapter->ctw)
1436 {
1437 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301438
Jeff Johnson295189b2012-06-20 16:38:30 -07001439 if(pAdapter->ops)
1440 {
1441 NoA.opp_ps = pAdapter->ops;
1442 NoA.ctWindow = pAdapter->ctw;
1443 NoA.duration = 0;
1444 NoA.single_noa_duration = 0;
1445 NoA.interval = 0;
1446 NoA.count = 0;
1447 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1448 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301449
Jeff Johnson295189b2012-06-20 16:38:30 -07001450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1451 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1452 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001453 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001454 NoA.ctWindow, NoA.duration, NoA.interval,
1455 NoA.count, NoA.single_noa_duration,
1456 NoA.psSelection);
1457
1458 sme_p2pSetPs(hHal, &NoA);
1459 }
1460 return 0;
1461 }
1462 }
1463
1464 if (opp_ps != -1)
1465 {
1466 pAdapter->ops = opp_ps;
1467
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301468 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001469 {
1470 NoA.opp_ps = opp_ps;
1471 NoA.ctWindow = pAdapter->ctw;
1472 NoA.duration = 0;
1473 NoA.single_noa_duration = 0;
1474 NoA.interval = 0;
1475 NoA.count = 0;
1476 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1477 NoA.sessionid = pAdapter->sessionId;
1478
1479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1480 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1481 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001482 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001483 NoA.ctWindow, NoA.duration, NoA.interval,
1484 NoA.count, NoA.single_noa_duration,
1485 NoA.psSelection);
1486
1487 sme_p2pSetPs(hHal, &NoA);
1488 }
1489 }
1490 return status;
1491}
1492
1493int hdd_setP2pPs( struct net_device *dev, void *msgData )
1494{
1495 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1496 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1497 VOS_STATUS status = VOS_STATUS_SUCCESS;
1498 tP2pPsConfig NoA;
1499 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1500
1501 NoA.opp_ps = pappNoA->opp_ps;
1502 NoA.ctWindow = pappNoA->ctWindow;
1503 NoA.duration = pappNoA->duration;
1504 NoA.interval = pappNoA->interval;
1505 NoA.count = pappNoA->count;
1506 NoA.single_noa_duration = pappNoA->single_noa_duration;
1507 NoA.psSelection = pappNoA->psSelection;
1508 NoA.sessionid = pAdapter->sessionId;
1509
1510 sme_p2pSetPs(hHal, &NoA);
1511 return status;
1512}
Jeff Johnson295189b2012-06-20 16:38:30 -07001513
1514static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1515{
1516 tANI_U8 sessionType;
1517
1518 switch( type )
1519 {
1520 case NL80211_IFTYPE_AP:
1521 sessionType = WLAN_HDD_SOFTAP;
1522 break;
1523 case NL80211_IFTYPE_P2P_GO:
1524 sessionType = WLAN_HDD_P2P_GO;
1525 break;
1526 case NL80211_IFTYPE_P2P_CLIENT:
1527 sessionType = WLAN_HDD_P2P_CLIENT;
1528 break;
1529 case NL80211_IFTYPE_STATION:
1530 sessionType = WLAN_HDD_INFRA_STATION;
1531 break;
1532 case NL80211_IFTYPE_MONITOR:
1533 sessionType = WLAN_HDD_MONITOR;
1534 break;
1535 default:
1536 sessionType = WLAN_HDD_INFRA_STATION;
1537 break;
1538 }
1539
1540 return sessionType;
1541}
1542
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001543#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1544struct wireless_dev* wlan_hdd_add_virtual_intf(
1545 struct wiphy *wiphy, const char *name,
1546 enum nl80211_iftype type,
1547 u32 *flags, struct vif_params *params )
1548#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1549struct wireless_dev* wlan_hdd_add_virtual_intf(
1550 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1551 u32 *flags, struct vif_params *params )
1552#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001553struct net_device* wlan_hdd_add_virtual_intf(
1554 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1555 u32 *flags, struct vif_params *params )
1556#else
1557int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1558 enum nl80211_iftype type,
1559 u32 *flags, struct vif_params *params )
1560#endif
1561{
1562 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301563 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001564 ENTER();
1565
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301566 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1567 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001568 if(hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
1569 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001570 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001571 "interfaces of same type are not supported currently.",__func__, type);
Jeff Johnsond13512a2012-07-17 11:42:19 -07001572 return NULL;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001573 }
1574
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001575 if (pHddCtx->isLogpInProgress)
1576 {
1577 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1578 "%s:LOGP in Progress. Ignore!!!", __func__);
1579#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1580 return NULL;
1581#else
1582 return -EAGAIN;
1583#endif
1584 }
Kiet Lam04e26912013-10-18 20:13:38 +05301585 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1586 ((NL80211_IFTYPE_P2P_GO == type) ||
1587 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001588 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001589 /* Generate the P2P Interface Address. this address must be
1590 * different from the P2P Device Address.
1591 */
1592 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1593 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301594 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001595 wlan_hdd_get_session_type(type),
1596 name, p2pDeviceAddress.bytes,
1597 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001598 }
1599 else
1600 {
1601 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1602 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1603 }
1604
1605 if( NULL == pAdapter)
1606 {
1607 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1608#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1609 return NULL;
1610#else
1611 return -EINVAL;
1612#endif
1613 }
1614 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001615#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1616 return pAdapter->dev->ieee80211_ptr;
1617#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001618 return pAdapter->dev;
1619#else
1620 return 0;
1621#endif
1622}
1623
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001624#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1625int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1626#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001627int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001628#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001629{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001630#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1631 struct net_device *dev = wdev->netdev;
1632#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301633 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301634 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301635 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1636 int status;
1637 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001638
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301639 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1640 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1641 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301642 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1643 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001644
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301645 status = wlan_hdd_validate_context(pHddCtx);
1646
1647 if (0 != status)
1648 {
1649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1650 "%s: HDD context is not valid", __func__);
1651 return status;
1652 }
1653
1654 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001655 pVirtAdapter->macAddressCurrent.bytes );
1656
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301657 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1658 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1659 EXIT();
1660 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001661}
1662
1663void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001664 tANI_U32 nFrameLength,
1665 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301666 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07001667{
1668 //Indicate a Frame over Monitor Intf.
1669 int rxstat;
1670 struct sk_buff *skb = NULL;
1671 int needed_headroom = 0;
1672 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1673 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001674#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001675#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1676 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1677#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001678#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001679 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1680
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001681 if (NULL == pbFrames)
1682 {
1683 hddLog(LOGE, FL("NULL frame pointer"));
1684 return;
1685 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001686
1687 /* room for the radiotap header based on driver features
1688 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1689 * RX flags.
1690 * */
1691 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1692
1693 //alloc skb here
1694 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1695 if (unlikely(NULL == skb))
1696 {
1697 hddLog( LOGW, FL("Unable to allocate skb"));
1698 return;
1699 }
1700 skb_reserve(skb, VPKT_SIZE_BUFFER);
1701 if (unlikely(skb_headroom(skb) < nFrameLength))
1702 {
1703 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1704 "HDD [%d]: Insufficient headroom, "
1705 "head[%p], data[%p], req[%d]",
1706 __LINE__, skb->head, skb->data, nFrameLength);
1707 kfree_skb(skb);
1708 return ;
1709 }
1710 // actually push the data
1711 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1712 /* prepend radiotap information */
1713 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1714 {
1715 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1716 //free skb
1717 kfree_skb(skb);
1718 return ;
1719 }
1720
1721 skb_reset_mac_header( skb );
1722 skb->dev = pMonAdapter->dev;
1723 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001724 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001725#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001726#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001727 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001728#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001729#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001730 rxstat = netif_rx_ni(skb);
1731 if( NET_RX_SUCCESS == rxstat )
1732 {
1733 hddLog( LOG1, FL("Success"));
1734 }
1735 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301736 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07001737
1738 return ;
1739}
1740
1741void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301742 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07001743 tANI_U8* pbFrames,
1744 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301745 tANI_U32 rxChan,
1746 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001747{
1748 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301749 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07001750 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001751 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001752 tActionFrmType actionFrmType;
1753 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301754 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05301755 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301756 VOS_STATUS status;
1757 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001758
Arif Hussain6d2a3322013-11-17 19:50:10 -08001759 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001760 __func__, frameType, nFrameLength);
1761
1762 if (NULL == pAdapter)
1763 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001764 hddLog(LOGE, FL("pAdapter is NULL"));
1765 return;
1766 }
1767
1768 if (0 == nFrameLength)
1769 {
1770 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
1771 return;
1772 }
1773
1774 if (NULL == pbFrames)
1775 {
1776 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001777 return;
1778 }
1779
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001780 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1781 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1782
1783 /* Get pAdapter from Destination mac address of the frame */
1784 if ((type == SIR_MAC_MGMT_FRAME) &&
1785 (subType != SIR_MAC_MGMT_PROBE_REQ))
1786 {
1787 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1788 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1789 if (NULL == pAdapter)
1790 {
1791 /* Under assumtion that we don't receive any action frame
1792 * with BCST as destination we dropping action frame
1793 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001794 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1795 MAC_ADDRESS_STR ,
1796 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1797 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08001798 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001799 return;
1800 }
1801 }
1802
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001803
Jeff Johnson295189b2012-06-20 16:38:30 -07001804 if (NULL == pAdapter->dev)
1805 {
1806 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1807 return;
1808 }
1809
1810 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1811 {
1812 hddLog( LOGE, FL("pAdapter has invalid magic"));
1813 return;
1814 }
1815
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301816 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1817 if (NULL == pHddCtx)
1818 {
1819 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
1820 return;
1821 }
1822
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001823 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1824 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001825 {
1826 hdd_adapter_t *pMonAdapter =
1827 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1828
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001829 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001830 {
1831 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1832 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1833 pbFrames, frameType);
1834 return;
1835 }
1836 }
1837
1838 //Channel indicated may be wrong. TODO
1839 //Indicate an action frame.
1840 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1841 {
1842 freq = ieee80211_channel_to_frequency( rxChan,
1843 IEEE80211_BAND_2GHZ);
1844 }
1845 else
1846 {
1847 freq = ieee80211_channel_to_frequency( rxChan,
1848 IEEE80211_BAND_5GHZ);
1849 }
1850
Jeff Johnsone7245742012-09-05 17:12:55 -07001851 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301852 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301853
1854 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001855 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001856 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001857 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1858 {
1859 // public action frame
1860 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001861 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 -08001862 // P2P action frames
1863 {
1864 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08001865 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001866#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001867 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1868 {
1869 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1870 actionFrmType);
1871 }
1872 else
1873 {
1874 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1875 p2p_action_frame_type[actionFrmType]);
1876 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1877 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1878 {
1879 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1880 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001881 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001882 }
1883 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1884 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1885 {
1886 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001887 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1888 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001889 }
1890 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1891 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1892 {
1893 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1894 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1895 " completed state Autonomous GO formation");
1896 }
1897 }
1898#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301899 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
1900 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
1901 {
1902 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1903 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
1904 actionFrmType == WLAN_HDD_INVITATION_REQ ||
1905 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
1906 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
1907 {
1908 hddLog( LOG1, "Extend RoC timer on reception of"
1909 " Action Frame");
1910 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
1911 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
1912 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
1913 else
1914 extend_time = ACTION_FRAME_DEFAULT_WAIT;
1915 if (completion_done(&pAdapter->rem_on_chan_ready_event))
1916 {
1917 vos_timer_stop(
1918 &pRemainChanCtx->hdd_remain_on_chan_timer);
1919 status = vos_timer_start(
1920 &pRemainChanCtx->hdd_remain_on_chan_timer,
1921 extend_time);
1922 if (status != VOS_STATUS_SUCCESS)
1923 {
1924 hddLog( LOGE, "ROC timer start failed");
1925 }
1926 }
1927 else
1928 {
1929 // Buffer Packet
1930 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
1931 {
1932 pRemainChanCtx->action_pkt_buff.frame_length =
1933 nFrameLength;
1934 pRemainChanCtx->action_pkt_buff.freq = freq;
1935 pRemainChanCtx->action_pkt_buff.frame_ptr
1936 = vos_mem_malloc(nFrameLength);
1937 vos_mem_copy(
1938 pRemainChanCtx->action_pkt_buff.frame_ptr,
1939 pbFrames, nFrameLength);
1940 hddLog( LOGE,"%s:"
1941 "Action Pkt Cached successfully !!!", __func__);
1942 }
1943 else
1944 {
1945 hddLog( LOGE,"%s:"
1946 "Frames are pending. dropping frame !!!",
1947 __func__);
1948 }
1949 return;
1950 }
1951 }
1952 }
1953 if (pRemainChanCtx != NULL &&
1954 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
1955 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
1956 hddLog( LOG1, "%s:"
1957 "Rcvd action frame after timer expired ", __func__);
1958
1959 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) ||
1960 (actionFrmType == WLAN_HDD_GO_NEG_REQ) ||
1961 (actionFrmType == WLAN_HDD_INVITATION_REQ) )
1962 {
1963 pScanInfo = &pHddCtx->scan_info;
1964 if((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
1965 {
1966 hddLog(LOGE,"Action frame received when Scanning is in"
1967 " progress. Abort Scan.");
1968 hdd_abort_mac_scan(pAdapter->pHddCtx,
1969 pAdapter->sessionId,
1970 eCSR_SCAN_ABORT_DEFAULT);
1971 }
1972 }
1973 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
1974 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
1975 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
1976 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
1977 {
1978 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
1979 __func__);
1980 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001981 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001982 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08001983#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001984 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 -07001985 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001986 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
1987#ifdef WLAN_FEATURE_TDLS_DEBUG
1988 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
1989 MAC_ADDR_ARRAY(mac),rxRssi);
1990#endif
1991 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
1992 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001993 }
1994#endif
1995 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07001996#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001997 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
1998 {
1999 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2000 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2001 {
2002 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2003 actionFrmType);
2004 }
2005 else
2006 {
2007 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2008 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002009 }
2010 }
2011#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002012 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2013 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2014 {
2015 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal, hddWmmDscpToUpMapInfra);
2016 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002017 }
2018
Jeff Johnson295189b2012-06-20 16:38:30 -07002019 //Indicate Frame Over Normal Interface
2020 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2021
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002022#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2023 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2024 pbFrames, nFrameLength,
2025 GFP_ATOMIC );
2026#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002027 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2028 pbFrames, nFrameLength,
2029 GFP_ATOMIC );
2030#else
2031 cfg80211_rx_mgmt( pAdapter->dev, freq,
2032 pbFrames, nFrameLength,
2033 GFP_ATOMIC );
2034#endif //LINUX_VERSION_CODE
2035}
2036
2037/*
2038 * ieee80211_add_rx_radiotap_header - add radiotap header
2039 */
2040static int hdd_wlan_add_rx_radiotap_hdr (
2041 struct sk_buff *skb, int rtap_len, int flag )
2042{
2043 u8 rtap_temp[20] = {0};
2044 struct ieee80211_radiotap_header *rthdr;
2045 unsigned char *pos;
2046 u16 rx_flags = 0;
2047
2048 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2049
2050 /* radiotap header, set always present flags */
2051 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2052 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2053 rthdr->it_len = cpu_to_le16(rtap_len);
2054
2055 pos = (unsigned char *) (rthdr + 1);
2056
2057 /* the order of the following fields is important */
2058
2059 /* IEEE80211_RADIOTAP_FLAGS */
2060 *pos = 0;
2061 pos++;
2062
2063 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2064 /* ensure 2 byte alignment for the 2 byte field as required */
2065 if ((pos - (u8 *)rthdr) & 1)
2066 pos++;
2067 put_unaligned_le16(rx_flags, pos);
2068 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302069
Jeff Johnson295189b2012-06-20 16:38:30 -07002070 // actually push the data
2071 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2072
2073 return 0;
2074}
2075
2076static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2077 hdd_cfg80211_state_t* cfgState,
2078 tANI_BOOLEAN actionSendSuccess )
2079{
2080 struct ieee80211_radiotap_header *rthdr;
2081 unsigned char *pos;
2082 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002083#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002084#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2085 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2086#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002087#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002088
2089 /* 2 Byte for TX flags and 1 Byte for Retry count */
2090 u32 rtHdrLen = sizeof(*rthdr) + 3;
2091
2092 u8 *data;
2093
2094 /* We have to return skb with Data starting with MAC header. We have
2095 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2096 * entire skb->len from skb and then we will push cfgState->buf to skb
2097 * */
2098 if( NULL == skb_pull(skb, skb->len) )
2099 {
2100 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2101 kfree_skb(cfgState->skb);
2102 return;
2103 }
2104
2105 data = skb_push( skb, cfgState->len );
2106
2107 if (data == NULL)
2108 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002109 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002110 kfree_skb( cfgState->skb );
2111 return;
2112 }
2113
2114 memcpy( data, cfgState->buf, cfgState->len );
2115
2116 /* send frame to monitor interfaces now */
2117 if( skb_headroom(skb) < rtHdrLen )
2118 {
2119 hddLog( LOGE, FL("No headroom for rtap header"));
2120 kfree_skb(cfgState->skb);
2121 return;
2122 }
2123
2124 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2125
2126 memset( rthdr, 0, rtHdrLen );
2127 rthdr->it_len = cpu_to_le16( rtHdrLen );
2128 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2129 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2130 );
2131
2132 pos = (unsigned char *)( rthdr+1 );
2133
2134 // Fill TX flags
2135 *pos = actionSendSuccess;
2136 pos += 2;
2137
2138 // Fill retry count
2139 *pos = 0;
2140 pos++;
2141
2142 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002143 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002144 skb->pkt_type = PACKET_OTHERHOST;
2145 skb->protocol = htons(ETH_P_802_2);
2146 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002147#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002148#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002149 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002150#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002151#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002152 if (in_interrupt())
2153 netif_rx( skb );
2154 else
2155 netif_rx_ni( skb );
2156
2157 /* Enable Queues which we have disabled earlier */
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302158 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002159
2160}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302161