blob: 10f0ba307a5788f6eea70a46c2eee86ab96e1e72 [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);
Daram Sudha1f7e0e92013-12-17 07:52:31 +053061tANI_U8* hdd_getActionString( tANI_U16 MsgType )
62{
63 switch (MsgType)
64 {
65 CASE_RETURN_STRING(SIR_MAC_ACTION_SPECTRUM_MGMT);
66 CASE_RETURN_STRING(SIR_MAC_ACTION_QOS_MGMT);
67 CASE_RETURN_STRING(SIR_MAC_ACTION_DLP);
68 CASE_RETURN_STRING(SIR_MAC_ACTION_BLKACK);
69 CASE_RETURN_STRING(SIR_MAC_ACTION_PUBLIC_USAGE);
70 CASE_RETURN_STRING(SIR_MAC_ACTION_RRM);
71 CASE_RETURN_STRING(SIR_MAC_ACTION_FAST_BSS_TRNST);
72 CASE_RETURN_STRING(SIR_MAC_ACTION_HT);
73 CASE_RETURN_STRING(SIR_MAC_ACTION_SA_QUERY);
74 CASE_RETURN_STRING(SIR_MAC_ACTION_PROT_DUAL_PUB);
75 CASE_RETURN_STRING(SIR_MAC_ACTION_WNM);
76 CASE_RETURN_STRING(SIR_MAC_ACTION_UNPROT_WNM);
77 CASE_RETURN_STRING(SIR_MAC_ACTION_TDLS);
78 CASE_RETURN_STRING(SIR_MAC_ACITON_MESH);
79 CASE_RETURN_STRING(SIR_MAC_ACTION_MULTIHOP);
80 CASE_RETURN_STRING(SIR_MAC_SELF_PROTECTED);
81 CASE_RETURN_STRING(SIR_MAC_ACTION_WME);
82 CASE_RETURN_STRING(SIR_MAC_ACTION_VHT);
83 default:
84 return ("UNKNOWN");
85 }
86}
87
88
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070089#ifdef WLAN_FEATURE_P2P_DEBUG
90#define MAX_P2P_ACTION_FRAME_TYPE 9
91const char *p2p_action_frame_type[]={"GO Negotiation Request",
92 "GO Negotiation Response",
93 "GO Negotiation Confirmation",
94 "P2P Invitation Request",
95 "P2P Invitation Response",
96 "Device Discoverability Request",
97 "Device Discoverability Response",
98 "Provision Discovery Request",
99 "Provision Discovery Response"};
100
101/* We no need to protect this variable since
102 * there is no chance of race to condition
103 * and also not make any complicating the code
104 * just for debugging log
105 */
106tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
107
108#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800109#ifdef WLAN_FEATURE_TDLS_DEBUG
110#define MAX_TDLS_ACTION_FRAME_TYPE 11
111const char *tdls_action_frame_type[] = {"TDLS Setup Request",
112 "TDLS Setup Response",
113 "TDLS Setup Confirm",
114 "TDLS Teardown",
115 "TDLS Peer Traffic Indication",
116 "TDLS Channel Switch Request",
117 "TDLS Channel Switch Response",
118 "TDLS Peer PSM Request",
119 "TDLS Peer PSM Response",
120 "TDLS Peer Traffic Response",
121 "TDLS Discovery Request" };
122#endif
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700123
Jeff Johnson295189b2012-06-20 16:38:30 -0700124extern struct net_device_ops net_ops_struct;
125
126static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
127 int rtap_len, int flag );
128
129static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
130 hdd_cfg80211_state_t* cfgState,
131 tANI_BOOLEAN actionSendSuccess );
132
133static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Rashmi Ramannac7744532013-10-06 16:49:08 +0530134 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -0700135 tANI_U8* pbFrames,
136 tANI_U8 frameType );
vamsi9bd92b72013-12-26 14:11:29 +0530137
138static v_BOOL_t hdd_p2p_is_action_type_rsp( const u8 *buf )
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530139{
vamsi9bd92b72013-12-26 14:11:29 +0530140 tActionFrmType actionFrmType;
141 const u8 *ouiPtr;
142
143 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
144 WLAN_HDD_PUBLIC_ACTION_FRAME ) {
145 return VOS_FALSE;
146 }
147
148 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] !=
149 WLAN_HDD_VENDOR_SPECIFIC_ACTION ) {
150 return VOS_FALSE;
151 }
152
153 ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET];
154
155 if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) {
156 return VOS_FALSE;
157 }
158
159 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] !=
160 WLAN_HDD_WFA_P2P_OUI_TYPE ) {
161 return VOS_FALSE;
162 }
163
Ahmad Kholaife5ec2cd2014-03-19 13:22:04 +0530164 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
vamsi9bd92b72013-12-26 14:11:29 +0530165 if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
166 actionFrmType != WLAN_HDD_GO_NEG_REQ &&
167 actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
168 actionFrmType != WLAN_HDD_PROV_DIS_REQ )
169 return VOS_TRUE;
170 else
171 return VOS_FALSE;
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530172}
Jeff Johnson295189b2012-06-20 16:38:30 -0700173
Jeff Johnson295189b2012-06-20 16:38:30 -0700174eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
175 eHalStatus status )
176{
177 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700178 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
179 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
180
181 if( pRemainChanCtx == NULL )
182 {
183 hddLog( LOGW,
184 "%s: No Rem on channel pending for which Rsp is received", __func__);
185 return eHAL_STATUS_SUCCESS;
186 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530187 hddLog( VOS_TRACE_LEVEL_INFO,
188 "Received ROC rsp (request type %d, channel %d, cookie %llu",
189 pRemainChanCtx->rem_on_chan_request,
190 pRemainChanCtx->chan.center_freq,
191 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192 cfgState->remain_on_chan_ctx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530193 vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
194 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
195 if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
Jeff Johnson295189b2012-06-20 16:38:30 -0700196 {
197 if( cfgState->buf )
198 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530199 hddLog( LOGP,
Jeff Johnson295189b2012-06-20 16:38:30 -0700200 "%s: We need to receive yet an ack from one of tx packet",
201 __func__);
202 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800203 cfg80211_remain_on_channel_expired(
204#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
205 pRemainChanCtx->dev->ieee80211_ptr,
206#else
207 pRemainChanCtx->dev,
208#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700209 pRemainChanCtx->cookie,
210 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700211#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
212 pRemainChanCtx->chan_type,
213#endif
214 GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 }
216
Jeff Johnson295189b2012-06-20 16:38:30 -0700217
218 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700219 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
220 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700221 )
222 {
223 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800224 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
225 {
226 sme_DeregisterMgmtFrame(
227 hHal, sessionId,
228 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
229 NULL, 0 );
230 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700231 }
232 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
233 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
234 )
235 {
236 WLANSAP_DeRegisterMgmtFrame(
237 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
238 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
239 NULL, 0 );
240 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530241 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
242 && pRemainChanCtx->action_pkt_buff.frame_length != 0)
243 {
244 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
245 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800246 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800247 pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700248 complete(&pAdapter->cancel_rem_on_chan_var);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530249 pAdapter->is_roc_inprogress = FALSE;
250 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 return eHAL_STATUS_SUCCESS;
252}
253
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530254VOS_STATUS wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700255{
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530257 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700258 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700259
Jeff Johnson32d95a32012-09-10 13:15:23 -0700260 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700261 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530262 hddLog(VOS_TRACE_LEVEL_INFO,
263 "Cancel Existing ROC (cookie=%llu)",
264 cfgState->remain_on_chan_ctx->cookie);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700265
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530266 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
267 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE)
268 {
269 hddLog( LOG1,
270 "ROC timer cancellation in progress,"
271 " wait for completion");
272 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
273 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
274 if (0 >= status)
275 {
276 hddLog( LOGE,
277 "%s:wait on cancel_rem_on_chan_var failed %d",
278 __func__, status);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530279 return VOS_STATUS_E_FAILURE;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530280 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530281 return VOS_STATUS_SUCCESS;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530282 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530283
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530284 /* Wait till remain on channel ready indication before issuing cancel
285 * remain on channel request, otherwise if remain on channel not
286 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 * will be in unknown state.
288 */
289 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
290 msecs_to_jiffies(WAIT_REM_CHAN_READY));
c_hpothu7f63e882013-10-02 19:13:35 +0530291 if (0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 {
293 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530294 "%s: timeout waiting for remain on channel ready indication %d",
295 __func__, status);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530296 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
297 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700298 }
299
300 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530301 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530302
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 /* Issue abort remain on chan request to sme.
304 * The remain on channel callback will make sure the remain_on_chan
305 * expired event is sent.
306 */
307 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700308 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
309 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 )
311 {
312 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
313 pAdapter->sessionId );
314 }
315 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
316 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
317 )
318 {
319 WLANSAP_CancelRemainOnChannel(
320 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
321 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700322
Jeff Johnson32d95a32012-09-10 13:15:23 -0700323 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700324 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700325
c_hpothu7f63e882013-10-02 19:13:35 +0530326 if (0 >= status)
Jeff Johnson32d95a32012-09-10 13:15:23 -0700327 {
328 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530329 "%s: timeout waiting for cancel remain on channel ready indication %d",
330 __func__, status);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700331 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530332 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700333 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530334 return VOS_STATUS_SUCCESS;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700335}
336
337int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
338{
339 int status = 0;
340 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
341
342 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
343 {
344 //Cancel Existing Remain On Channel
345 //If no action frame is pending
346 if( cfgState->remain_on_chan_ctx != NULL)
347 {
348 //Check whether Action Frame is pending or not
349 if( cfgState->buf == NULL)
350 {
351 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
352 }
353 else
354 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530355 hddLog(VOS_TRACE_LEVEL_DEBUG,
356 "Cannot Cancel Existing Remain on Channel");
Jeff Johnson32d95a32012-09-10 13:15:23 -0700357 status = -EBUSY;
358 }
359 }
360 }
361 return status;
362}
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530363void wlan_hdd_remain_on_chan_timeout(void *data)
364{
365 hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
366 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
367 hdd_cfg80211_state_t *cfgState;
368 if ( NULL == pAdapter )
369 {
370 hddLog( LOGE, FL("pAdapter is NULL !!!"));
371 return;
372 }
373 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
374 pRemainChanCtx = cfgState->remain_on_chan_ctx;
375 if (NULL == pRemainChanCtx)
376 {
377 hddLog( LOGE, FL("No Remain on channel is pending"));
378 return;
379 }
380 if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
381 {
382 hddLog( LOGE, FL("Cancellation already in progress"));
383 return;
384 }
385
386 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
387 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
388 hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
389 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
390 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
391 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
392 )
393 {
394 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
395 pAdapter->sessionId );
396 }
397 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
398 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
399 )
400 {
401 WLANSAP_CancelRemainOnChannel(
402 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
403 }
404 hdd_allow_suspend();
405}
Jeff Johnson32d95a32012-09-10 13:15:23 -0700406
407static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
408 struct net_device *dev,
409 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700410#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700411 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700412#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700413 unsigned int duration, u64 *cookie,
414 rem_on_channel_request_type_t request_type )
415{
416 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
417 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
418 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530419 VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
420 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
421 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
422 hdd_adapter_t *pAdapter_temp;
423 VOS_STATUS status;
424 v_BOOL_t isGoPresent = VOS_FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530425 VOS_STATUS checkReadyInd;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700426 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
427 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700428#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530429 hddLog(VOS_TRACE_LEVEL_INFO,
430 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
431 " request type %d, cookie %llu",
432 chan->hw_value, chan->center_freq, channel_type, duration,
433 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700434#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530435 hddLog(VOS_TRACE_LEVEL_INFO,
436 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
437 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
438 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700439#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700440 //Cancel existing remain On Channel if any
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530441 checkReadyInd = wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
442 if (VOS_STATUS_SUCCESS != checkReadyInd)
443 {
444 hddLog( LOGE, FL("Cancel Roc in progress"));
445 return -EBUSY;
446 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700447
Jeff Johnsone7245742012-09-05 17:12:55 -0700448 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700449 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700450 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700451 * channel requets when Load/Unload is in progress*/
Rashmi Ramannab1429032014-04-26 14:59:09 +0530452 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(((hdd_context_t *)pAdapter->pHddCtx))
453 || hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx))
Jeff Johnson295189b2012-06-20 16:38:30 -0700454 {
455 hddLog( LOGE,
Rashmi Ramannab1429032014-04-26 14:59:09 +0530456 "%s: Wlan Load/Unload or Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700457 return -EBUSY;
458 }
459
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700460 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
461 {
462 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
463 "%s:LOGP in Progress. Ignore!!!", __func__);
464 return -EAGAIN;
465 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700466 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
467 if( NULL == pRemainChanCtx )
468 {
469 hddLog(VOS_TRACE_LEVEL_FATAL,
470 "%s: Not able to allocate memory for Channel context",
471 __func__);
472 return -ENOMEM;
473 }
474
475 vos_mem_copy( &pRemainChanCtx->chan, chan,
476 sizeof(struct ieee80211_channel) );
477
Yue Maf49ba872013-08-19 12:04:25 -0700478#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700479 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700480#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700481 pRemainChanCtx->duration = duration;
482 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800483 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700484 pRemainChanCtx->cookie = *cookie;
485 pRemainChanCtx->rem_on_chan_request = request_type;
486 cfgState->remain_on_chan_ctx = pRemainChanCtx;
487 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530488 pRemainChanCtx->action_pkt_buff.freq = 0;
489 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
490 pRemainChanCtx->action_pkt_buff.frame_length = 0;
491 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530492 pRemainChanCtx->is_pending_roc_cancelled = FALSE;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530493 /* Initialize Remain on chan timer */
494 vos_status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
495 VOS_TIMER_TYPE_SW,
496 wlan_hdd_remain_on_chan_timeout,
497 pAdapter);
498 if (vos_status != VOS_STATUS_SUCCESS)
499 {
500 hddLog(VOS_TRACE_LEVEL_ERROR,
501 "%s: Not able to initalize remain_on_chan timer", __func__);
502 }
503 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
504 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
505 {
506 pAdapter_temp = pAdapterNode->pAdapter;
507 if (WLAN_HDD_P2P_GO == pAdapter_temp->device_mode)
508 {
509 isGoPresent = VOS_TRUE;
510 }
511 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
512 pAdapterNode = pNext;
513 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530514 hdd_prevent_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700515 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
516
517 //call sme API to start remain on channel.
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 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700523 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700524 //call sme API to start remain on channel.
525 sme_RemainOnChannel(
Rashmi Ramannac7744532013-10-06 16:49:08 +0530526 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
527 chan->hw_value, duration,
528 wlan_hdd_remain_on_channel_callback, pAdapter,
529 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700530
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800531 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
532 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530533 if( eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame(
534 WLAN_HDD_GET_HAL_CTX(pAdapter),
535 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
536 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ))
537 {
538 hddLog(VOS_TRACE_LEVEL_ERROR,
539 "sme_RegisterMgmtFrame returned fail");
540 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800541 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700542
543 }
544 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
545 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
546 )
547 {
548 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700549 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700550 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
551 chan->hw_value, duration,
552 wlan_hdd_remain_on_channel_callback, pAdapter ))
553
554 {
555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
556 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
557 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700558 vos_mem_free (pRemainChanCtx);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530559 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700560 return -EINVAL;
561 }
562
563
Jeff Johnson43971f52012-07-17 12:26:56 -0700564 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700565 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
566 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
567 NULL, 0 ))
568 {
569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
570 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
571 WLANSAP_CancelRemainOnChannel(
572 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530573 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700574 return -EINVAL;
575 }
576
577 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530578
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530579 pAdapter->is_roc_inprogress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700580 return 0;
581
582}
583
584int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800585#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
586 struct wireless_dev *wdev,
587#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700588 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800589#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700590 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700591#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700592 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700593#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700594 unsigned int duration, u64 *cookie )
595{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800596#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
597 struct net_device *dev = wdev->netdev;
598#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530599 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
600
601 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
602 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
603 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Jeff Johnson295189b2012-06-20 16:38:30 -0700604 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700605 chan,
606#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
607 channel_type,
608#endif
609 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700610 REMAIN_ON_CHANNEL_REQUEST);
611}
612
613void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
614{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530615 hdd_cfg80211_state_t *cfgState = NULL;
616 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530617 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530618 if (NULL == pAdapter)
619 {
620 hddLog(LOGE, FL("pAdapter is NULL"));
621 return;
622 }
623 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
624 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530625 hddLog( LOG1, "Ready on chan ind");
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 if( pRemainChanCtx != NULL )
627 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530628 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
629 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
630 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530631 //start timer for actual duration
632 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
633 (pRemainChanCtx->duration));
634 if (VOS_STATUS_SUCCESS!=status)
635 {
636 hddLog( LOGE, FL("Remain on Channel timer start failed"));
637 }
638 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700639 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800640 cfg80211_ready_on_channel(
641#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
642 pAdapter->dev->ieee80211_ptr,
643#else
644 pAdapter->dev,
645#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800646 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700647 &pRemainChanCtx->chan,
648#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
649 pRemainChanCtx->chan_type,
650#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700651 pRemainChanCtx->duration, GFP_KERNEL );
652 }
653#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530654 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700655 {
656 complete(&pAdapter->offchannel_tx_event);
657 }
658#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530659 // Check for cached action frame
660 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
661 {
662#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
663 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
664 pRemainChanCtx->action_pkt_buff.freq, 0,
665 pRemainChanCtx->action_pkt_buff.frame_ptr,
666 pRemainChanCtx->action_pkt_buff.frame_length,
667 GFP_ATOMIC );
668#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
669 cfg80211_rx_mgmt( pAdapter->dev,
670 pRemainChanCtx->action_pkt_buff.freq, 0,
671 pRemainChanCtx->action_pkt_buff.frame_ptr,
672 pRemainChanCtx->action_pkt_buff.frame_length,
673 GFP_ATOMIC );
674#else
675 cfg80211_rx_mgmt( pAdapter->dev,
676 pRemainChanCtx->action_pkt_buff.freq,
677 pRemainChanCtx->action_pkt_buff.frame_ptr,
678 pRemainChanCtx->action_pkt_buff.frame_length,
679 GFP_ATOMIC );
680#endif //LINUX_VERSION_CODE
681 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
682 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
683 pRemainChanCtx->action_pkt_buff.frame_length = 0;
684 pRemainChanCtx->action_pkt_buff.freq = 0;
685 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
686 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530687 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
688 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700689 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530690 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
691 {
692 /* since pRemainChanCtx->is_pending_roc_cancelled is
693 * set, it means Cancel Reamain on channel command is
694 * pending because remain on channel event was not
695 * ready when cancel ROC was issued.So issue
696 * cancel ROC now.
697 */
698 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
699 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700700 }
701 else
702 {
703 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
704 }
705 return;
706}
707
708int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800709#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
710 struct wireless_dev *wdev,
711#else
712 struct net_device *dev,
713#endif
714 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700715{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800716#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
717 struct net_device *dev = wdev->netdev;
718#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700719 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700720 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530721 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530722 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
723 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530724 u64 cookie_dummy;
725 cookie_dummy = cookie << 32;
726 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
727 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
728 pAdapter->sessionId, cookie_dummy));
729 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -0700730
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530731 status = wlan_hdd_validate_context(pHddCtx);
732
733 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700734 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530735 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
736 "%s: HDD context is not valid", __func__);
737 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700738 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530739 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
740
Jeff Johnson295189b2012-06-20 16:38:30 -0700741 /* FIXME cancel currently running remain on chan.
742 * Need to check cookie and cancel accordingly
743 */
744 if( (cfgState->remain_on_chan_ctx == NULL) ||
745 (cfgState->remain_on_chan_ctx->cookie != cookie) )
746 {
747 hddLog( LOGE,
748 "%s: No Remain on channel pending with specified cookie value",
749 __func__);
750 return -EINVAL;
751 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530752 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
753 {
754 /* wait until remain on channel ready event received
755 * for already issued remain on channel request */
756 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
757 msecs_to_jiffies(WAIT_REM_CHAN_READY));
758 if (0 >= status)
759 {
760 hddLog( LOGE,
761 "%s: timeout waiting for remain on channel ready indication %d",
762 __func__, status);
763 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
764 return 0;
765
766 }
767 }
768 else
769 {
770 hddLog( LOG1, FL("Cancel ROC event is already pending, "
771 "waiting for ready on channel indication.") );
772 return 0;
773 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530774 if (NULL != cfgState->remain_on_chan_ctx)
775 {
776 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
777 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
778 {
779 hddLog( LOG1,
780 FL("ROC timer cancellation in progress,"
781 " wait for completion"));
782 status = wait_for_completion_interruptible_timeout(
783 &pAdapter->cancel_rem_on_chan_var,
784 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
785 if (0 >= status)
786 {
787 hddLog( LOGE,
788 "%s:wait on cancel_rem_on_chan_var failed %d",
789 __func__, status);
790 }
791 return 0;
792 }
793 else
794 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
795 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700796 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
797 /* Issue abort remain on chan request to sme.
798 * The remain on channel callback will make sure the remain_on_chan
799 * expired event is sent.
800 */
801 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700802 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
803 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700804 )
805 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530806 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700807 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
808 sessionId );
809 }
810 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
811 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
812 )
813 {
814 WLANSAP_CancelRemainOnChannel(
815 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
816 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530817 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700818 {
819 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
820 __func__, pAdapter->device_mode);
821 return -EIO;
822 }
c_hpothu7f63e882013-10-02 19:13:35 +0530823 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700824 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +0530825 if (0 >= status)
826 {
827 hddLog( LOGE,
828 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
829 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530830 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700831 return 0;
832}
833
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800834#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530835int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800836 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700837#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800838 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700839 bool channel_type_valid,
840#endif
841 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800842 const u8 *buf, size_t len, bool no_cck,
843 bool dont_wait_for_ack, u64 *cookie )
844#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530845int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700846 struct ieee80211_channel *chan, bool offchan,
847 enum nl80211_channel_type channel_type,
848 bool channel_type_valid, unsigned int wait,
849 const u8 *buf, size_t len, bool no_cck,
850 bool dont_wait_for_ack, u64 *cookie )
851#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530852int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700853 struct ieee80211_channel *chan, bool offchan,
854 enum nl80211_channel_type channel_type,
855 bool channel_type_valid, unsigned int wait,
856 const u8 *buf, size_t len, u64 *cookie )
857#else
DARAM SUDHA39eede62014-02-12 11:16:40 +0530858int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700859 struct ieee80211_channel *chan,
860 enum nl80211_channel_type channel_type,
861 bool channel_type_valid,
862 const u8 *buf, size_t len, u64 *cookie )
863#endif //LINUX_VERSION_CODE
864{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800865#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
866 struct net_device *dev = wdev->netdev;
867#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700868 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +0530869 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
870 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
871 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700872 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
873 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
874 tActionFrmType actionFrmType;
875 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530876 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -0700877
Jeff Johnson295189b2012-06-20 16:38:30 -0700878#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
879 hdd_adapter_t *goAdapter;
880#endif
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +0530881
882 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530883 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
884 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530885 status = wlan_hdd_validate_context(pHddCtx);
886
887 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800888 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
890 "%s: HDD context is not valid", __func__);
891 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800892 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530893
c_hpothu7f63e882013-10-02 19:13:35 +0530894 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
895 __func__, pAdapter->device_mode, type);
896
897
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700898#ifdef WLAN_FEATURE_P2P_DEBUG
899 if ((type == SIR_MAC_MGMT_FRAME) &&
900 (subType == SIR_MAC_MGMT_ACTION) &&
901 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
902 {
903 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800904 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700905 {
906 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
907 actionFrmType);
908 }
909 else
910 {
911 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
912 p2p_action_frame_type[actionFrmType]);
913 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
914 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
915 {
916 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
917 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800918 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700919 }
920 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
921 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
922 {
923 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
924 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
925 " completed state");
926 }
927 }
928 }
929#endif
930
Jeff Johnsone7245742012-09-05 17:12:55 -0700931#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
932 noack = dont_wait_for_ack;
933#endif
934
935 //If the wait is coming as 0 with off channel set
936 //then set the wait to 200 ms
937 if (offchan && !wait)
938 wait = ACTION_FRAME_DEFAULT_WAIT;
939
Jeff Johnson295189b2012-06-20 16:38:30 -0700940 //Call sme API to send out a action frame.
941 // OR can we send it directly through data path??
942 // After tx completion send tx status back.
943 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
944 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
945 )
946 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700947 if (type == SIR_MAC_MGMT_FRAME)
948 {
949 if (subType == SIR_MAC_MGMT_PROBE_RSP)
950 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530951 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -0700952 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530953 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700954 goto err_rem_channel;
955 }
956 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
957 (subType == SIR_MAC_MGMT_DEAUTH))
958 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700959 /* During EAP failure or P2P Group Remove supplicant
960 * is sending del_station command to driver. From
961 * del_station function, Driver will send deauth frame to
962 * p2p client. No need to send disassoc frame from here.
963 * so Drop the frame here and send tx indication back to
964 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700965 */
966 tANI_U8 dstMac[ETH_ALEN] = {0};
967 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700968 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700969 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -0800970 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -0700971 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -0800972 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700973 goto err_rem_channel;
974 }
975 }
976 }
977
978 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800979 {
980 if ( !noack )
981 {
982 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
983 __func__);
984 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
985 }
986 else
987 {
988 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
989 __func__);
990 return -EBUSY;
991 }
992 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700993
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530994 if( subType == SIR_MAC_MGMT_ACTION)
995 {
996 hddLog( LOG1, "Action frame tx request : %s",
997 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
998 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700999
1000#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1001 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1002
1003 //If GO adapter exists and operating on same frequency
1004 //then we will not request remain on channel
1005 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1006 == goAdapter->sessionCtx.ap.operatingChannel ) )
1007 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301008 /* if GO exist and is not off channel
1009 * wait time should be zero.
1010 */
1011 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001012 goto send_frame;
1013 }
1014#endif
1015
1016#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1017 if( offchan && wait)
1018 {
1019 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301020 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001021 // In case of P2P Client mode if we are already
1022 // on the same channel then send the frame directly
1023
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301024 if( (cfgState->remain_on_chan_ctx != NULL) &&
1025 (cfgState->current_freq == chan->center_freq)
1026 )
1027 {
1028 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1029 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301030 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301031 /* Some times FW is taking almost 500 msec for
1032 * full 15 retries, which leads to ROC expiration
1033 * by the time peer gets response from other peer.
1034 * Therefore as part of temporary fix , in host
1035 * ROC time is extended. For frames where we are
1036 * expecting response from peer , its extended by
1037 * 500 msec to make ROC wait time as 1 sec and
1038 * in other cases its extended by 300 msec to make
1039 * total ROC wait as 500 msec.
1040 * TODO: FW needs to fix as why 15 retry is taking
1041 * such long time.
1042 */
1043 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1044 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1045 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1046 wait = wait + ACTION_FRAME_RSP_WAIT;
1047 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1048 actionFrmType == WLAN_HDD_INVITATION_RESP )
1049 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301050 vos_timer_stop(
1051 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1052 status = vos_timer_start(
1053 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1054 wait);
1055 if ( status != VOS_STATUS_SUCCESS )
vamsida0e5ab2013-12-26 14:33:27 +05301056 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301057 hddLog( LOGE, "Remain on Channel timer start failed");
1058 }
1059
1060 hddLog(VOS_TRACE_LEVEL_INFO,
1061 "action frame: extending the wait time %u",
1062 wait);
1063 goto send_frame;
1064 }
1065 else
1066 {
1067 if ( TRUE ==
1068 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1069 {
1070 hddLog(VOS_TRACE_LEVEL_INFO,
1071 "action frame tx: waiting for completion of ROC ");
1072
1073 status = wait_for_completion_interruptible_timeout(
1074 &pAdapter->cancel_rem_on_chan_var,
1075 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1076 if (0 >= status)
1077 {
1078 hddLog( LOGE,
1079 "%s:wait on cancel_rem_on_chan_var failed %d",
1080 __func__, status);
1081 }
vamsida0e5ab2013-12-26 14:33:27 +05301082 }
1083 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301084 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301085 hddLog(VOS_TRACE_LEVEL_INFO,
1086 "action frame: Request ROC for wait time %u", wait);
1087
Jeff Johnson295189b2012-06-20 16:38:30 -07001088 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001089 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001090 chan,
1091#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1092 channel_type,
1093#endif
1094 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301095 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001096
1097 if(0 != status)
1098 {
1099 if( (-EBUSY == status) &&
1100 (cfgState->current_freq == chan->center_freq) )
1101 {
1102 goto send_frame;
1103 }
1104 goto err_rem_channel;
1105 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001106 /* Wait for driver to be ready on the requested channel */
1107 status = wait_for_completion_interruptible_timeout(
1108 &pAdapter->offchannel_tx_event,
1109 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301110 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001111 {
c_hpothu7f63e882013-10-02 19:13:35 +05301112 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001113 goto err_rem_channel;
1114 }
1115 }
1116 else if ( offchan )
1117 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001118 /* Check before sending action frame
1119 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001120 if(NULL == cfgState->remain_on_chan_ctx)
1121 {
1122 goto err_rem_channel;
1123 }
1124 }
1125 send_frame:
1126#endif
1127
Jeff Johnsone7245742012-09-05 17:12:55 -07001128 if(!noack)
1129 {
1130 cfgState->buf = vos_mem_malloc( len ); //buf;
1131 if( cfgState->buf == NULL )
1132 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001133
Jeff Johnsone7245742012-09-05 17:12:55 -07001134 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001135
Jeff Johnsone7245742012-09-05 17:12:55 -07001136 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001137
1138#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001139 if( cfgState->remain_on_chan_ctx )
1140 {
1141 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1142 *cookie = cfgState->action_cookie;
1143 }
1144 else
1145 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001146#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001147 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001148 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001149#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001150 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001151#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301152 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001153
1154 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001155 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1156 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001157 )
1158 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001159 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001160
Jeff Johnsone7245742012-09-05 17:12:55 -07001161 if ((type == SIR_MAC_MGMT_FRAME) &&
1162 (subType == SIR_MAC_MGMT_ACTION) &&
1163 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001164 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001165 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301166 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001167 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001168 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001169 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301170 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001171 }
1172 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1173 {
1174 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301175 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 }
1177 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301178
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 if (eHAL_STATUS_SUCCESS !=
1180 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301181 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001182 {
1183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1184 "%s: sme_sendAction returned fail", __func__);
1185 goto err;
1186 }
1187 }
1188 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1189 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1190 )
1191 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001192 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001193 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001194 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001195 {
1196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1197 "%s: WLANSAP_SendAction returned fail", __func__);
1198 goto err;
1199 }
1200 }
1201
1202 return 0;
1203err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001204 if(!noack)
1205 {
1206 hdd_sendActionCnf( pAdapter, FALSE );
1207 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001208 return 0;
1209err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001210 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001211 cfg80211_mgmt_tx_status(
1212#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1213 pAdapter->dev->ieee80211_ptr,
1214#else
1215 pAdapter->dev,
1216#endif
1217 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001218 return 0;
1219}
1220
1221#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001222#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1223int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1224 struct wireless_dev *wdev,
1225 u64 cookie)
1226{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301227 u64 cookie_dummy;
1228 cookie_dummy = cookie << 32;
1229 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1230 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001231 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1232}
1233#else
1234int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001235 struct net_device *dev,
1236 u64 cookie)
1237{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301238 u64 cookie_dummy;
1239 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1240 cookie_dummy = cookie << 32;
1241 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1242 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1243 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001244 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1245}
1246#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001247#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001248
1249void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1250{
1251 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1252
Jeff Johnsone7245742012-09-05 17:12:55 -07001253 cfgState->actionFrmState = HDD_IDLE;
1254
Jeff Johnson295189b2012-06-20 16:38:30 -07001255 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1256 if( NULL == cfgState->buf )
1257 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001258 return;
1259 }
1260
1261 /* If skb is NULL it means this packet was received on CFG80211 interface
1262 * else it was received on Monitor interface */
1263 if( cfgState->skb == NULL )
1264 {
1265 /*
1266 * buf is the same pointer it passed us to send. Since we are sending
1267 * it through control path, we use different buffers.
1268 * In case of mac80211, they just push it to the skb and pass the same
1269 * data while sending tx ack status.
1270 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001271 cfg80211_mgmt_tx_status(
1272#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1273 pAdapter->dev->ieee80211_ptr,
1274#else
1275 pAdapter->dev,
1276#endif
1277 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001278 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1279 vos_mem_free( cfgState->buf );
1280 cfgState->buf = NULL;
1281 }
1282 else
1283 {
1284 hdd_adapter_t* pMonAdapter =
1285 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1286 if( pMonAdapter == NULL )
1287 {
1288 hddLog( LOGE, "Not able to get Monitor Adapter");
1289 cfgState->skb = NULL;
1290 vos_mem_free( cfgState->buf );
1291 cfgState->buf = NULL;
1292 complete(&pAdapter->tx_action_cnf_event);
1293 return;
1294 }
1295 /* Send TX completion feedback over monitor interface. */
1296 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1297 cfgState->skb = NULL;
1298 vos_mem_free( cfgState->buf );
1299 cfgState->buf = NULL;
1300 /* Look for the next Mgmt packet to TX */
1301 hdd_mon_tx_mgmt_pkt(pAdapter);
1302 }
1303 complete(&pAdapter->tx_action_cnf_event);
1304}
1305
1306/**
1307 * hdd_setP2pNoa
1308 *
1309 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301310 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001311 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1312 *
1313 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301314 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001315 *
1316 *ASSUMPTIONS:
1317 *
1318 *
1319 *NOTE:
1320 *
1321 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301322 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001323 *
1324 * @return Status
1325 */
1326
1327int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1328{
1329 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1330 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1331 VOS_STATUS status = VOS_STATUS_SUCCESS;
1332 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001333 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001334 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001335 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001336
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001337 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001338 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301339 {
1340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1341 "%s: strnchr failed to find delimeter",__func__);
1342 return -EINVAL;
1343 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001344 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001345 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1346 if (ret < 3)
1347 {
1348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1349 "%s: P2P_SET GO NoA: fail to read param "
1350 "count=%d duration=%d interval=%d \n",
1351 __func__, count, start_time, duration);
1352 return -EINVAL;
1353 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001355 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001356 __func__, count, start_time, duration);
1357 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001358 /* PS Selection
1359 * Periodic NoA (2)
1360 * Single NOA (4)
1361 */
1362 NoA.opp_ps = 0;
1363 NoA.ctWindow = 0;
1364 if (count == 1)
1365 {
1366 NoA.duration = 0;
1367 NoA.single_noa_duration = duration;
1368 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1369 }
1370 else
1371 {
1372 NoA.duration = duration;
1373 NoA.single_noa_duration = 0;
1374 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1375 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001376 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001377 NoA.count = count;
1378 NoA.sessionid = pAdapter->sessionId;
1379
1380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1381 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1382 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001383 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001384 NoA.ctWindow, NoA.duration, NoA.interval,
1385 NoA.count, NoA.single_noa_duration,
1386 NoA.psSelection);
1387
1388 sme_p2pSetPs(hHal, &NoA);
1389 return status;
1390}
1391
1392/**
1393 * hdd_setP2pOpps
1394 *
1395 *FUNCTION:
1396 * This function is called from hdd_hostapd_ioctl function when Driver
1397 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1398 *
1399 *LOGIC:
1400 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1401 *
1402 *ASSUMPTIONS:
1403 *
1404 *
1405 *NOTE:
1406 *
1407 * @param dev Pointer to net device structure
1408 * @param command Pointer to command
1409 *
1410 * @return Status
1411 */
1412
1413int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1414{
1415 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1416 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1417 VOS_STATUS status = VOS_STATUS_SUCCESS;
1418 tP2pPsConfig NoA;
1419 char *param;
1420 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001421 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001422
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001423 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001424 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301425 {
1426 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1427 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001428 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301429 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001430 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001431 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1432 if (ret < 3)
1433 {
1434 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1435 "%s: P2P_SET GO PS: fail to read param "
1436 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1437 __func__, legacy_ps, opp_ps, ctwindow);
1438 return -EINVAL;
1439 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001440 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001441 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001442 __func__, legacy_ps, opp_ps, ctwindow);
1443
1444 /* PS Selection
1445 * Opportunistic Power Save (1)
1446 */
1447
1448 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1449 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301450 * values are coming from wpa_supplicant as -1.
1451 * Example : User want to set ctWindow with 30 then wpa_cli command :
1452 * P2P_SET ctwindow 30
1453 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001454 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301455 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001456 if (ctwindow != -1)
1457 {
1458
1459 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001460 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001461 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1462
1463 if (ctwindow != pAdapter->ctw)
1464 {
1465 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301466
Jeff Johnson295189b2012-06-20 16:38:30 -07001467 if(pAdapter->ops)
1468 {
1469 NoA.opp_ps = pAdapter->ops;
1470 NoA.ctWindow = pAdapter->ctw;
1471 NoA.duration = 0;
1472 NoA.single_noa_duration = 0;
1473 NoA.interval = 0;
1474 NoA.count = 0;
1475 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1476 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301477
Jeff Johnson295189b2012-06-20 16:38:30 -07001478 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1479 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1480 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001481 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001482 NoA.ctWindow, NoA.duration, NoA.interval,
1483 NoA.count, NoA.single_noa_duration,
1484 NoA.psSelection);
1485
1486 sme_p2pSetPs(hHal, &NoA);
1487 }
1488 return 0;
1489 }
1490 }
1491
1492 if (opp_ps != -1)
1493 {
1494 pAdapter->ops = opp_ps;
1495
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301496 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001497 {
1498 NoA.opp_ps = opp_ps;
1499 NoA.ctWindow = pAdapter->ctw;
1500 NoA.duration = 0;
1501 NoA.single_noa_duration = 0;
1502 NoA.interval = 0;
1503 NoA.count = 0;
1504 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1505 NoA.sessionid = pAdapter->sessionId;
1506
1507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1508 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1509 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001510 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001511 NoA.ctWindow, NoA.duration, NoA.interval,
1512 NoA.count, NoA.single_noa_duration,
1513 NoA.psSelection);
1514
1515 sme_p2pSetPs(hHal, &NoA);
1516 }
1517 }
1518 return status;
1519}
1520
1521int hdd_setP2pPs( struct net_device *dev, void *msgData )
1522{
1523 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1524 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1525 VOS_STATUS status = VOS_STATUS_SUCCESS;
1526 tP2pPsConfig NoA;
1527 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1528
1529 NoA.opp_ps = pappNoA->opp_ps;
1530 NoA.ctWindow = pappNoA->ctWindow;
1531 NoA.duration = pappNoA->duration;
1532 NoA.interval = pappNoA->interval;
1533 NoA.count = pappNoA->count;
1534 NoA.single_noa_duration = pappNoA->single_noa_duration;
1535 NoA.psSelection = pappNoA->psSelection;
1536 NoA.sessionid = pAdapter->sessionId;
1537
1538 sme_p2pSetPs(hHal, &NoA);
1539 return status;
1540}
Jeff Johnson295189b2012-06-20 16:38:30 -07001541
1542static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1543{
1544 tANI_U8 sessionType;
1545
1546 switch( type )
1547 {
1548 case NL80211_IFTYPE_AP:
1549 sessionType = WLAN_HDD_SOFTAP;
1550 break;
1551 case NL80211_IFTYPE_P2P_GO:
1552 sessionType = WLAN_HDD_P2P_GO;
1553 break;
1554 case NL80211_IFTYPE_P2P_CLIENT:
1555 sessionType = WLAN_HDD_P2P_CLIENT;
1556 break;
1557 case NL80211_IFTYPE_STATION:
1558 sessionType = WLAN_HDD_INFRA_STATION;
1559 break;
1560 case NL80211_IFTYPE_MONITOR:
1561 sessionType = WLAN_HDD_MONITOR;
1562 break;
1563 default:
1564 sessionType = WLAN_HDD_INFRA_STATION;
1565 break;
1566 }
1567
1568 return sessionType;
1569}
1570
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001571#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1572struct wireless_dev* wlan_hdd_add_virtual_intf(
1573 struct wiphy *wiphy, const char *name,
1574 enum nl80211_iftype type,
1575 u32 *flags, struct vif_params *params )
1576#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1577struct wireless_dev* wlan_hdd_add_virtual_intf(
1578 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1579 u32 *flags, struct vif_params *params )
1580#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001581struct net_device* wlan_hdd_add_virtual_intf(
1582 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1583 u32 *flags, struct vif_params *params )
1584#else
1585int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1586 enum nl80211_iftype type,
1587 u32 *flags, struct vif_params *params )
1588#endif
1589{
1590 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301591 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301592 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001593 ENTER();
1594
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301595 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1596 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301597 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1598 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1599 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001600 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001601 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001602 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05301603#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1604 return ERR_PTR(-EINVAL);
1605#else
1606 return -EAGAIN;
1607#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001608 }
1609
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001610 if (pHddCtx->isLogpInProgress)
1611 {
1612 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1613 "%s:LOGP in Progress. Ignore!!!", __func__);
1614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301615 return ERR_PTR(-EINVAL);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001616#else
1617 return -EAGAIN;
1618#endif
1619 }
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301620
1621 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1622 pScanInfo = &pHddCtx->scan_info;
1623 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1624 (pHddCtx->scan_info.mScanPending))
1625 {
1626 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1627 eCSR_SCAN_ABORT_DEFAULT);
1628 hddLog(VOS_TRACE_LEVEL_INFO,
1629 "%s: Abort Scan while adding virtual interface",__func__);
1630 }
1631
1632 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05301633 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1634 ((NL80211_IFTYPE_P2P_GO == type) ||
1635 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001636 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001637 /* Generate the P2P Interface Address. this address must be
1638 * different from the P2P Device Address.
1639 */
1640 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1641 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301642 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001643 wlan_hdd_get_session_type(type),
1644 name, p2pDeviceAddress.bytes,
1645 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001646 }
1647 else
1648 {
1649 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1650 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1651 }
1652
1653 if( NULL == pAdapter)
1654 {
1655 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1656#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301657 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001658#else
1659 return -EINVAL;
1660#endif
1661 }
1662 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001663#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1664 return pAdapter->dev->ieee80211_ptr;
1665#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001666 return pAdapter->dev;
1667#else
1668 return 0;
1669#endif
1670}
1671
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001672#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1673int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1674#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001675int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001676#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001677{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001678#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1679 struct net_device *dev = wdev->netdev;
1680#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301681 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301682 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301683 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1684 int status;
1685 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001686
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301687 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1688 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1689 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301690 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1691 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001692
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301693 status = wlan_hdd_validate_context(pHddCtx);
1694
1695 if (0 != status)
1696 {
1697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1698 "%s: HDD context is not valid", __func__);
1699 return status;
1700 }
1701
1702 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001703 pVirtAdapter->macAddressCurrent.bytes );
1704
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05301705 hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301706 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1707 EXIT();
1708 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001709}
1710
1711void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001712 tANI_U32 nFrameLength,
1713 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301714 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07001715{
1716 //Indicate a Frame over Monitor Intf.
1717 int rxstat;
1718 struct sk_buff *skb = NULL;
1719 int needed_headroom = 0;
1720 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1721 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001722#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001723#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1724 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1725#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001726#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001727 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1728
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001729 if (NULL == pbFrames)
1730 {
1731 hddLog(LOGE, FL("NULL frame pointer"));
1732 return;
1733 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001734
1735 /* room for the radiotap header based on driver features
1736 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1737 * RX flags.
1738 * */
1739 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1740
1741 //alloc skb here
1742 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1743 if (unlikely(NULL == skb))
1744 {
1745 hddLog( LOGW, FL("Unable to allocate skb"));
1746 return;
1747 }
1748 skb_reserve(skb, VPKT_SIZE_BUFFER);
1749 if (unlikely(skb_headroom(skb) < nFrameLength))
1750 {
1751 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1752 "HDD [%d]: Insufficient headroom, "
1753 "head[%p], data[%p], req[%d]",
1754 __LINE__, skb->head, skb->data, nFrameLength);
1755 kfree_skb(skb);
1756 return ;
1757 }
1758 // actually push the data
1759 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1760 /* prepend radiotap information */
1761 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1762 {
1763 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1764 //free skb
1765 kfree_skb(skb);
1766 return ;
1767 }
1768
1769 skb_reset_mac_header( skb );
1770 skb->dev = pMonAdapter->dev;
1771 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001772 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001773#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001774#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001775 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001776#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001777#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001778 rxstat = netif_rx_ni(skb);
1779 if( NET_RX_SUCCESS == rxstat )
1780 {
1781 hddLog( LOG1, FL("Success"));
1782 }
1783 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301784 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07001785
1786 return ;
1787}
1788
1789void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301790 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07001791 tANI_U8* pbFrames,
1792 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301793 tANI_U32 rxChan,
1794 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001795{
1796 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301797 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07001798 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001799 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001800 tActionFrmType actionFrmType;
1801 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301802 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05301803 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301804 VOS_STATUS status;
1805 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001806
Arif Hussain6d2a3322013-11-17 19:50:10 -08001807 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001808 __func__, frameType, nFrameLength);
1809
1810 if (NULL == pAdapter)
1811 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001812 hddLog(LOGE, FL("pAdapter is NULL"));
1813 return;
1814 }
1815
1816 if (0 == nFrameLength)
1817 {
1818 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
1819 return;
1820 }
1821
1822 if (NULL == pbFrames)
1823 {
1824 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001825 return;
1826 }
1827
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001828 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1829 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1830
1831 /* Get pAdapter from Destination mac address of the frame */
1832 if ((type == SIR_MAC_MGMT_FRAME) &&
1833 (subType != SIR_MAC_MGMT_PROBE_REQ))
1834 {
1835 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1836 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1837 if (NULL == pAdapter)
1838 {
1839 /* Under assumtion that we don't receive any action frame
1840 * with BCST as destination we dropping action frame
1841 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001842 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1843 MAC_ADDRESS_STR ,
1844 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1845 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08001846 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001847 return;
1848 }
1849 }
1850
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001851
Jeff Johnson295189b2012-06-20 16:38:30 -07001852 if (NULL == pAdapter->dev)
1853 {
1854 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1855 return;
1856 }
1857
1858 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1859 {
1860 hddLog( LOGE, FL("pAdapter has invalid magic"));
1861 return;
1862 }
1863
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301864 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1865 if (NULL == pHddCtx)
1866 {
1867 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
1868 return;
1869 }
1870
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001871 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1872 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001873 {
1874 hdd_adapter_t *pMonAdapter =
1875 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1876
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001877 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001878 {
1879 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1880 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1881 pbFrames, frameType);
1882 return;
1883 }
1884 }
1885
1886 //Channel indicated may be wrong. TODO
1887 //Indicate an action frame.
1888 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1889 {
1890 freq = ieee80211_channel_to_frequency( rxChan,
1891 IEEE80211_BAND_2GHZ);
1892 }
1893 else
1894 {
1895 freq = ieee80211_channel_to_frequency( rxChan,
1896 IEEE80211_BAND_5GHZ);
1897 }
1898
Jeff Johnsone7245742012-09-05 17:12:55 -07001899 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301900 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301901
1902 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001903 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001904 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001905 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1906 {
1907 // public action frame
1908 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001909 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 -08001910 // P2P action frames
1911 {
1912 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08001913 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001914#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001915 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1916 {
1917 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1918 actionFrmType);
1919 }
1920 else
1921 {
1922 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1923 p2p_action_frame_type[actionFrmType]);
1924 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1925 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1926 {
1927 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1928 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001929 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001930 }
1931 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1932 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1933 {
1934 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001935 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1936 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001937 }
1938 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1939 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1940 {
1941 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1942 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1943 " completed state Autonomous GO formation");
1944 }
1945 }
1946#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301947 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
1948 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
1949 {
1950 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1951 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
1952 actionFrmType == WLAN_HDD_INVITATION_REQ ||
1953 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
1954 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
1955 {
1956 hddLog( LOG1, "Extend RoC timer on reception of"
1957 " Action Frame");
1958 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
1959 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
1960 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
1961 else
1962 extend_time = ACTION_FRAME_DEFAULT_WAIT;
1963 if (completion_done(&pAdapter->rem_on_chan_ready_event))
1964 {
1965 vos_timer_stop(
1966 &pRemainChanCtx->hdd_remain_on_chan_timer);
1967 status = vos_timer_start(
1968 &pRemainChanCtx->hdd_remain_on_chan_timer,
1969 extend_time);
1970 if (status != VOS_STATUS_SUCCESS)
1971 {
1972 hddLog( LOGE, "ROC timer start failed");
1973 }
1974 }
1975 else
1976 {
1977 // Buffer Packet
1978 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
1979 {
1980 pRemainChanCtx->action_pkt_buff.frame_length =
1981 nFrameLength;
1982 pRemainChanCtx->action_pkt_buff.freq = freq;
1983 pRemainChanCtx->action_pkt_buff.frame_ptr
1984 = vos_mem_malloc(nFrameLength);
1985 vos_mem_copy(
1986 pRemainChanCtx->action_pkt_buff.frame_ptr,
1987 pbFrames, nFrameLength);
1988 hddLog( LOGE,"%s:"
1989 "Action Pkt Cached successfully !!!", __func__);
1990 }
1991 else
1992 {
1993 hddLog( LOGE,"%s:"
1994 "Frames are pending. dropping frame !!!",
1995 __func__);
1996 }
1997 return;
1998 }
1999 }
2000 }
2001 if (pRemainChanCtx != NULL &&
2002 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2003 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2004 hddLog( LOG1, "%s:"
2005 "Rcvd action frame after timer expired ", __func__);
2006
2007 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) ||
2008 (actionFrmType == WLAN_HDD_GO_NEG_REQ) ||
2009 (actionFrmType == WLAN_HDD_INVITATION_REQ) )
2010 {
2011 pScanInfo = &pHddCtx->scan_info;
2012 if((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2013 {
2014 hddLog(LOGE,"Action frame received when Scanning is in"
2015 " progress. Abort Scan.");
2016 hdd_abort_mac_scan(pAdapter->pHddCtx,
2017 pAdapter->sessionId,
2018 eCSR_SCAN_ABORT_DEFAULT);
2019 }
2020 }
2021 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2022 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2023 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2024 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2025 {
2026 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2027 __func__);
2028 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002029 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002030 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002031#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002032 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 -07002033 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002034 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
2035#ifdef WLAN_FEATURE_TDLS_DEBUG
2036 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2037 MAC_ADDR_ARRAY(mac),rxRssi);
2038#endif
2039 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2040 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002041 }
2042#endif
2043 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002044#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002045 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2046 {
2047 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2048 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2049 {
2050 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2051 actionFrmType);
2052 }
2053 else
2054 {
2055 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2056 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002057 }
2058 }
2059#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002060 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2061 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2062 {
Kumar Anand82c009f2014-05-29 00:29:42 -07002063 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
2064 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002065 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002066 }
2067
Jeff Johnson295189b2012-06-20 16:38:30 -07002068 //Indicate Frame Over Normal Interface
2069 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2070
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002071#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2072 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2073 pbFrames, nFrameLength,
2074 GFP_ATOMIC );
2075#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002076 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2077 pbFrames, nFrameLength,
2078 GFP_ATOMIC );
2079#else
2080 cfg80211_rx_mgmt( pAdapter->dev, freq,
2081 pbFrames, nFrameLength,
2082 GFP_ATOMIC );
2083#endif //LINUX_VERSION_CODE
2084}
2085
2086/*
2087 * ieee80211_add_rx_radiotap_header - add radiotap header
2088 */
2089static int hdd_wlan_add_rx_radiotap_hdr (
2090 struct sk_buff *skb, int rtap_len, int flag )
2091{
2092 u8 rtap_temp[20] = {0};
2093 struct ieee80211_radiotap_header *rthdr;
2094 unsigned char *pos;
2095 u16 rx_flags = 0;
2096
2097 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2098
2099 /* radiotap header, set always present flags */
2100 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2101 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2102 rthdr->it_len = cpu_to_le16(rtap_len);
2103
2104 pos = (unsigned char *) (rthdr + 1);
2105
2106 /* the order of the following fields is important */
2107
2108 /* IEEE80211_RADIOTAP_FLAGS */
2109 *pos = 0;
2110 pos++;
2111
2112 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2113 /* ensure 2 byte alignment for the 2 byte field as required */
2114 if ((pos - (u8 *)rthdr) & 1)
2115 pos++;
2116 put_unaligned_le16(rx_flags, pos);
2117 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302118
Jeff Johnson295189b2012-06-20 16:38:30 -07002119 // actually push the data
2120 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2121
2122 return 0;
2123}
2124
2125static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2126 hdd_cfg80211_state_t* cfgState,
2127 tANI_BOOLEAN actionSendSuccess )
2128{
2129 struct ieee80211_radiotap_header *rthdr;
2130 unsigned char *pos;
2131 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002132#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002133#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2134 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2135#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002136#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002137
2138 /* 2 Byte for TX flags and 1 Byte for Retry count */
2139 u32 rtHdrLen = sizeof(*rthdr) + 3;
2140
2141 u8 *data;
2142
2143 /* We have to return skb with Data starting with MAC header. We have
2144 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2145 * entire skb->len from skb and then we will push cfgState->buf to skb
2146 * */
2147 if( NULL == skb_pull(skb, skb->len) )
2148 {
2149 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2150 kfree_skb(cfgState->skb);
2151 return;
2152 }
2153
2154 data = skb_push( skb, cfgState->len );
2155
2156 if (data == NULL)
2157 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002158 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002159 kfree_skb( cfgState->skb );
2160 return;
2161 }
2162
2163 memcpy( data, cfgState->buf, cfgState->len );
2164
2165 /* send frame to monitor interfaces now */
2166 if( skb_headroom(skb) < rtHdrLen )
2167 {
2168 hddLog( LOGE, FL("No headroom for rtap header"));
2169 kfree_skb(cfgState->skb);
2170 return;
2171 }
2172
2173 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2174
2175 memset( rthdr, 0, rtHdrLen );
2176 rthdr->it_len = cpu_to_le16( rtHdrLen );
2177 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2178 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2179 );
2180
2181 pos = (unsigned char *)( rthdr+1 );
2182
2183 // Fill TX flags
2184 *pos = actionSendSuccess;
2185 pos += 2;
2186
2187 // Fill retry count
2188 *pos = 0;
2189 pos++;
2190
2191 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002192 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002193 skb->pkt_type = PACKET_OTHERHOST;
2194 skb->protocol = htons(ETH_P_802_2);
2195 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002196#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002197#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002198 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002199#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002200#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002201 if (in_interrupt())
2202 netif_rx( skb );
2203 else
2204 netif_rx_ni( skb );
2205
2206 /* Enable Queues which we have disabled earlier */
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302207 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002208
2209}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302210