blob: 9adc017c3d5d50fd15c9a7e3b5ca58ebc767b71a [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 );
Sushant Kaushik10728722014-05-14 16:20:25 +0530600 if (NULL == pAdapter)
601 {
602 hddLog(LOGE, FL("pAdapter is NULL"));
603 return -ENODEV;
604 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530605
606 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
607 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
608 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Jeff Johnson295189b2012-06-20 16:38:30 -0700609 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700610 chan,
611#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
612 channel_type,
613#endif
614 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700615 REMAIN_ON_CHANNEL_REQUEST);
616}
617
618void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
619{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530620 hdd_cfg80211_state_t *cfgState = NULL;
621 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530622 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530623 if (NULL == pAdapter)
624 {
625 hddLog(LOGE, FL("pAdapter is NULL"));
626 return;
627 }
628 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
629 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530630 hddLog( LOG1, "Ready on chan ind");
Jeff Johnson295189b2012-06-20 16:38:30 -0700631 if( pRemainChanCtx != NULL )
632 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530633 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
634 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
635 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530636 //start timer for actual duration
637 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
638 (pRemainChanCtx->duration));
639 if (VOS_STATUS_SUCCESS!=status)
640 {
641 hddLog( LOGE, FL("Remain on Channel timer start failed"));
642 }
643 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700644 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800645 cfg80211_ready_on_channel(
646#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
647 pAdapter->dev->ieee80211_ptr,
648#else
649 pAdapter->dev,
650#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800651 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700652 &pRemainChanCtx->chan,
653#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
654 pRemainChanCtx->chan_type,
655#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700656 pRemainChanCtx->duration, GFP_KERNEL );
657 }
658#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530659 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700660 {
661 complete(&pAdapter->offchannel_tx_event);
662 }
663#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530664 // Check for cached action frame
665 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
666 {
667#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
668 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
669 pRemainChanCtx->action_pkt_buff.freq, 0,
670 pRemainChanCtx->action_pkt_buff.frame_ptr,
671 pRemainChanCtx->action_pkt_buff.frame_length,
672 GFP_ATOMIC );
673#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
674 cfg80211_rx_mgmt( pAdapter->dev,
675 pRemainChanCtx->action_pkt_buff.freq, 0,
676 pRemainChanCtx->action_pkt_buff.frame_ptr,
677 pRemainChanCtx->action_pkt_buff.frame_length,
678 GFP_ATOMIC );
679#else
680 cfg80211_rx_mgmt( pAdapter->dev,
681 pRemainChanCtx->action_pkt_buff.freq,
682 pRemainChanCtx->action_pkt_buff.frame_ptr,
683 pRemainChanCtx->action_pkt_buff.frame_length,
684 GFP_ATOMIC );
685#endif //LINUX_VERSION_CODE
686 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
687 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
688 pRemainChanCtx->action_pkt_buff.frame_length = 0;
689 pRemainChanCtx->action_pkt_buff.freq = 0;
690 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
691 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530692 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
693 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700694 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530695 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
696 {
697 /* since pRemainChanCtx->is_pending_roc_cancelled is
698 * set, it means Cancel Reamain on channel command is
699 * pending because remain on channel event was not
700 * ready when cancel ROC was issued.So issue
701 * cancel ROC now.
702 */
703 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
704 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700705 }
706 else
707 {
708 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
709 }
710 return;
711}
712
713int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800714#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
715 struct wireless_dev *wdev,
716#else
717 struct net_device *dev,
718#endif
719 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700720{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800721#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
722 struct net_device *dev = wdev->netdev;
723#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700724 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700725 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530726 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530727 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
728 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530729 u64 cookie_dummy;
730 cookie_dummy = cookie << 32;
731 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
732 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
733 pAdapter->sessionId, cookie_dummy));
734 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -0700735
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530736 status = wlan_hdd_validate_context(pHddCtx);
737
738 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700739 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530740 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
741 "%s: HDD context is not valid", __func__);
742 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700743 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530744 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
745
Jeff Johnson295189b2012-06-20 16:38:30 -0700746 /* FIXME cancel currently running remain on chan.
747 * Need to check cookie and cancel accordingly
748 */
749 if( (cfgState->remain_on_chan_ctx == NULL) ||
750 (cfgState->remain_on_chan_ctx->cookie != cookie) )
751 {
752 hddLog( LOGE,
753 "%s: No Remain on channel pending with specified cookie value",
754 __func__);
755 return -EINVAL;
756 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530757 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
758 {
759 /* wait until remain on channel ready event received
760 * for already issued remain on channel request */
761 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
762 msecs_to_jiffies(WAIT_REM_CHAN_READY));
763 if (0 >= status)
764 {
765 hddLog( LOGE,
766 "%s: timeout waiting for remain on channel ready indication %d",
767 __func__, status);
768 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
769 return 0;
770
771 }
772 }
773 else
774 {
775 hddLog( LOG1, FL("Cancel ROC event is already pending, "
776 "waiting for ready on channel indication.") );
777 return 0;
778 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530779 if (NULL != cfgState->remain_on_chan_ctx)
780 {
781 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
782 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
783 {
784 hddLog( LOG1,
785 FL("ROC timer cancellation in progress,"
786 " wait for completion"));
787 status = wait_for_completion_interruptible_timeout(
788 &pAdapter->cancel_rem_on_chan_var,
789 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
790 if (0 >= status)
791 {
792 hddLog( LOGE,
793 "%s:wait on cancel_rem_on_chan_var failed %d",
794 __func__, status);
795 }
796 return 0;
797 }
798 else
799 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
800 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700801 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
802 /* Issue abort remain on chan request to sme.
803 * The remain on channel callback will make sure the remain_on_chan
804 * expired event is sent.
805 */
806 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700807 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
808 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700809 )
810 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530811 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700812 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
813 sessionId );
814 }
815 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
816 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
817 )
818 {
819 WLANSAP_CancelRemainOnChannel(
820 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
821 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530822 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700823 {
824 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
825 __func__, pAdapter->device_mode);
826 return -EIO;
827 }
c_hpothu7f63e882013-10-02 19:13:35 +0530828 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700829 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +0530830 if (0 >= status)
831 {
832 hddLog( LOGE,
833 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
834 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530835 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700836 return 0;
837}
838
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800839#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530840int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800841 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700842#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800843 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700844 bool channel_type_valid,
845#endif
846 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800847 const u8 *buf, size_t len, bool no_cck,
848 bool dont_wait_for_ack, u64 *cookie )
849#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530850int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700851 struct ieee80211_channel *chan, bool offchan,
852 enum nl80211_channel_type channel_type,
853 bool channel_type_valid, unsigned int wait,
854 const u8 *buf, size_t len, bool no_cck,
855 bool dont_wait_for_ack, u64 *cookie )
856#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530857int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700858 struct ieee80211_channel *chan, bool offchan,
859 enum nl80211_channel_type channel_type,
860 bool channel_type_valid, unsigned int wait,
861 const u8 *buf, size_t len, u64 *cookie )
862#else
DARAM SUDHA39eede62014-02-12 11:16:40 +0530863int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700864 struct ieee80211_channel *chan,
865 enum nl80211_channel_type channel_type,
866 bool channel_type_valid,
867 const u8 *buf, size_t len, u64 *cookie )
868#endif //LINUX_VERSION_CODE
869{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800870#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
871 struct net_device *dev = wdev->netdev;
872#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700873 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Sushant Kaushik10728722014-05-14 16:20:25 +0530874 hdd_cfg80211_state_t *cfgState = NULL;
875 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
876 hdd_context_t *pHddCtx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700877 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
878 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
879 tActionFrmType actionFrmType;
880 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530881 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -0700882
Jeff Johnson295189b2012-06-20 16:38:30 -0700883#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
884 hdd_adapter_t *goAdapter;
885#endif
Sushant Kaushik10728722014-05-14 16:20:25 +0530886 if (NULL == pAdapter)
887 {
888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
889 "%s: HDD adapter context is Null", __func__);
890 return -ENODEV;
891 }
892 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530893 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
894 pAdapter->device_mode ));
Sushant Kaushik10728722014-05-14 16:20:25 +0530895 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
896 if (NULL == cfgState)
897 {
898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
899 "%s: cfg state is Null", __func__);
900 return -ENODEV;
901 }
902 pRemainChanCtx = cfgState->remain_on_chan_ctx;
903 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530904 status = wlan_hdd_validate_context(pHddCtx);
905
906 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800907 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530908 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
909 "%s: HDD context is not valid", __func__);
910 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800911 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530912
c_hpothu7f63e882013-10-02 19:13:35 +0530913 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
914 __func__, pAdapter->device_mode, type);
915
916
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700917#ifdef WLAN_FEATURE_P2P_DEBUG
918 if ((type == SIR_MAC_MGMT_FRAME) &&
919 (subType == SIR_MAC_MGMT_ACTION) &&
920 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
921 {
922 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800923 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700924 {
925 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
926 actionFrmType);
927 }
928 else
929 {
930 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
931 p2p_action_frame_type[actionFrmType]);
932 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
933 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
934 {
935 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
936 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800937 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700938 }
939 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
940 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
941 {
942 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
943 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
944 " completed state");
945 }
946 }
947 }
948#endif
949
Jeff Johnsone7245742012-09-05 17:12:55 -0700950#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
951 noack = dont_wait_for_ack;
952#endif
953
954 //If the wait is coming as 0 with off channel set
955 //then set the wait to 200 ms
956 if (offchan && !wait)
957 wait = ACTION_FRAME_DEFAULT_WAIT;
958
Jeff Johnson295189b2012-06-20 16:38:30 -0700959 //Call sme API to send out a action frame.
960 // OR can we send it directly through data path??
961 // After tx completion send tx status back.
962 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
963 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
964 )
965 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700966 if (type == SIR_MAC_MGMT_FRAME)
967 {
968 if (subType == SIR_MAC_MGMT_PROBE_RSP)
969 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530970 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -0700971 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530972 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700973 goto err_rem_channel;
974 }
975 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
976 (subType == SIR_MAC_MGMT_DEAUTH))
977 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700978 /* During EAP failure or P2P Group Remove supplicant
979 * is sending del_station command to driver. From
980 * del_station function, Driver will send deauth frame to
981 * p2p client. No need to send disassoc frame from here.
982 * so Drop the frame here and send tx indication back to
983 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700984 */
985 tANI_U8 dstMac[ETH_ALEN] = {0};
986 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700987 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700988 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -0800989 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -0700990 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -0800991 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700992 goto err_rem_channel;
993 }
994 }
995 }
996
997 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800998 {
999 if ( !noack )
1000 {
1001 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1002 __func__);
1003 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1004 }
1005 else
1006 {
1007 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1008 __func__);
1009 return -EBUSY;
1010 }
1011 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001012
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301013 if( subType == SIR_MAC_MGMT_ACTION)
1014 {
1015 hddLog( LOG1, "Action frame tx request : %s",
1016 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1017 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001018
1019#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1020 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1021
1022 //If GO adapter exists and operating on same frequency
1023 //then we will not request remain on channel
1024 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1025 == goAdapter->sessionCtx.ap.operatingChannel ) )
1026 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301027 /* if GO exist and is not off channel
1028 * wait time should be zero.
1029 */
1030 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001031 goto send_frame;
1032 }
1033#endif
1034
1035#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1036 if( offchan && wait)
1037 {
1038 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301039 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001040 // In case of P2P Client mode if we are already
1041 // on the same channel then send the frame directly
1042
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301043 if( (cfgState->remain_on_chan_ctx != NULL) &&
1044 (cfgState->current_freq == chan->center_freq)
1045 )
1046 {
1047 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1048 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301049 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301050 /* Some times FW is taking almost 500 msec for
1051 * full 15 retries, which leads to ROC expiration
1052 * by the time peer gets response from other peer.
1053 * Therefore as part of temporary fix , in host
1054 * ROC time is extended. For frames where we are
1055 * expecting response from peer , its extended by
1056 * 500 msec to make ROC wait time as 1 sec and
1057 * in other cases its extended by 300 msec to make
1058 * total ROC wait as 500 msec.
1059 * TODO: FW needs to fix as why 15 retry is taking
1060 * such long time.
1061 */
1062 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1063 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1064 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1065 wait = wait + ACTION_FRAME_RSP_WAIT;
1066 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1067 actionFrmType == WLAN_HDD_INVITATION_RESP )
1068 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301069 vos_timer_stop(
1070 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1071 status = vos_timer_start(
1072 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1073 wait);
1074 if ( status != VOS_STATUS_SUCCESS )
vamsida0e5ab2013-12-26 14:33:27 +05301075 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301076 hddLog( LOGE, "Remain on Channel timer start failed");
1077 }
1078
1079 hddLog(VOS_TRACE_LEVEL_INFO,
1080 "action frame: extending the wait time %u",
1081 wait);
1082 goto send_frame;
1083 }
1084 else
1085 {
1086 if ( TRUE ==
1087 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1088 {
1089 hddLog(VOS_TRACE_LEVEL_INFO,
1090 "action frame tx: waiting for completion of ROC ");
1091
1092 status = wait_for_completion_interruptible_timeout(
1093 &pAdapter->cancel_rem_on_chan_var,
1094 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1095 if (0 >= status)
1096 {
1097 hddLog( LOGE,
1098 "%s:wait on cancel_rem_on_chan_var failed %d",
1099 __func__, status);
1100 }
vamsida0e5ab2013-12-26 14:33:27 +05301101 }
1102 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301103 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301104 hddLog(VOS_TRACE_LEVEL_INFO,
1105 "action frame: Request ROC for wait time %u", wait);
1106
Jeff Johnson295189b2012-06-20 16:38:30 -07001107 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001109 chan,
1110#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1111 channel_type,
1112#endif
1113 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301114 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001115
1116 if(0 != status)
1117 {
1118 if( (-EBUSY == status) &&
1119 (cfgState->current_freq == chan->center_freq) )
1120 {
1121 goto send_frame;
1122 }
1123 goto err_rem_channel;
1124 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001125 /* Wait for driver to be ready on the requested channel */
1126 status = wait_for_completion_interruptible_timeout(
1127 &pAdapter->offchannel_tx_event,
1128 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301129 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001130 {
c_hpothu7f63e882013-10-02 19:13:35 +05301131 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001132 goto err_rem_channel;
1133 }
1134 }
1135 else if ( offchan )
1136 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001137 /* Check before sending action frame
1138 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001139 if(NULL == cfgState->remain_on_chan_ctx)
1140 {
1141 goto err_rem_channel;
1142 }
1143 }
1144 send_frame:
1145#endif
1146
Jeff Johnsone7245742012-09-05 17:12:55 -07001147 if(!noack)
1148 {
1149 cfgState->buf = vos_mem_malloc( len ); //buf;
1150 if( cfgState->buf == NULL )
1151 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001152
Jeff Johnsone7245742012-09-05 17:12:55 -07001153 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001154
Jeff Johnsone7245742012-09-05 17:12:55 -07001155 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001156
1157#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001158 if( cfgState->remain_on_chan_ctx )
1159 {
1160 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1161 *cookie = cfgState->action_cookie;
1162 }
1163 else
1164 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001165#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001166 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001167 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001168#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001169 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001170#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301171 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001172
1173 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001174 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1175 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 )
1177 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001178 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001179
Jeff Johnsone7245742012-09-05 17:12:55 -07001180 if ((type == SIR_MAC_MGMT_FRAME) &&
1181 (subType == SIR_MAC_MGMT_ACTION) &&
1182 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001183 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001184 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301185 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001186 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001187 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001188 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301189 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001190 }
1191 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1192 {
1193 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301194 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001195 }
1196 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301197
Jeff Johnson295189b2012-06-20 16:38:30 -07001198 if (eHAL_STATUS_SUCCESS !=
1199 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301200 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001201 {
1202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1203 "%s: sme_sendAction returned fail", __func__);
1204 goto err;
1205 }
1206 }
1207 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1208 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1209 )
1210 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001211 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001212 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001213 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001214 {
1215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1216 "%s: WLANSAP_SendAction returned fail", __func__);
1217 goto err;
1218 }
1219 }
1220
1221 return 0;
1222err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001223 if(!noack)
1224 {
1225 hdd_sendActionCnf( pAdapter, FALSE );
1226 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001227 return 0;
1228err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001229 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001230 cfg80211_mgmt_tx_status(
1231#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1232 pAdapter->dev->ieee80211_ptr,
1233#else
1234 pAdapter->dev,
1235#endif
1236 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001237 return 0;
1238}
1239
1240#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001241#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1242int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1243 struct wireless_dev *wdev,
1244 u64 cookie)
1245{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301246 u64 cookie_dummy;
1247 cookie_dummy = cookie << 32;
1248 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1249 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001250 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1251}
1252#else
1253int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001254 struct net_device *dev,
1255 u64 cookie)
1256{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301257 u64 cookie_dummy;
1258 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1259 cookie_dummy = cookie << 32;
1260 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1261 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1262 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001263 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1264}
1265#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001266#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001267
1268void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1269{
1270 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1271
Jeff Johnsone7245742012-09-05 17:12:55 -07001272 cfgState->actionFrmState = HDD_IDLE;
1273
Jeff Johnson295189b2012-06-20 16:38:30 -07001274 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1275 if( NULL == cfgState->buf )
1276 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001277 return;
1278 }
1279
1280 /* If skb is NULL it means this packet was received on CFG80211 interface
1281 * else it was received on Monitor interface */
1282 if( cfgState->skb == NULL )
1283 {
1284 /*
1285 * buf is the same pointer it passed us to send. Since we are sending
1286 * it through control path, we use different buffers.
1287 * In case of mac80211, they just push it to the skb and pass the same
1288 * data while sending tx ack status.
1289 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001290 cfg80211_mgmt_tx_status(
1291#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1292 pAdapter->dev->ieee80211_ptr,
1293#else
1294 pAdapter->dev,
1295#endif
1296 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001297 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1298 vos_mem_free( cfgState->buf );
1299 cfgState->buf = NULL;
1300 }
1301 else
1302 {
1303 hdd_adapter_t* pMonAdapter =
1304 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1305 if( pMonAdapter == NULL )
1306 {
1307 hddLog( LOGE, "Not able to get Monitor Adapter");
1308 cfgState->skb = NULL;
1309 vos_mem_free( cfgState->buf );
1310 cfgState->buf = NULL;
1311 complete(&pAdapter->tx_action_cnf_event);
1312 return;
1313 }
1314 /* Send TX completion feedback over monitor interface. */
1315 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1316 cfgState->skb = NULL;
1317 vos_mem_free( cfgState->buf );
1318 cfgState->buf = NULL;
1319 /* Look for the next Mgmt packet to TX */
1320 hdd_mon_tx_mgmt_pkt(pAdapter);
1321 }
1322 complete(&pAdapter->tx_action_cnf_event);
1323}
1324
1325/**
1326 * hdd_setP2pNoa
1327 *
1328 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301329 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001330 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1331 *
1332 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301333 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001334 *
1335 *ASSUMPTIONS:
1336 *
1337 *
1338 *NOTE:
1339 *
1340 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301341 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001342 *
1343 * @return Status
1344 */
1345
1346int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1347{
1348 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1349 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1350 VOS_STATUS status = VOS_STATUS_SUCCESS;
1351 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001352 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001353 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001354 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001355
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001356 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001357 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301358 {
1359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1360 "%s: strnchr failed to find delimeter",__func__);
1361 return -EINVAL;
1362 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001363 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001364 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1365 if (ret < 3)
1366 {
1367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1368 "%s: P2P_SET GO NoA: fail to read param "
1369 "count=%d duration=%d interval=%d \n",
1370 __func__, count, start_time, duration);
1371 return -EINVAL;
1372 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001373 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001374 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001375 __func__, count, start_time, duration);
1376 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001377 /* PS Selection
1378 * Periodic NoA (2)
1379 * Single NOA (4)
1380 */
1381 NoA.opp_ps = 0;
1382 NoA.ctWindow = 0;
1383 if (count == 1)
1384 {
1385 NoA.duration = 0;
1386 NoA.single_noa_duration = duration;
1387 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1388 }
1389 else
1390 {
1391 NoA.duration = duration;
1392 NoA.single_noa_duration = 0;
1393 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1394 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001395 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001396 NoA.count = count;
1397 NoA.sessionid = pAdapter->sessionId;
1398
1399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1400 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1401 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001402 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001403 NoA.ctWindow, NoA.duration, NoA.interval,
1404 NoA.count, NoA.single_noa_duration,
1405 NoA.psSelection);
1406
1407 sme_p2pSetPs(hHal, &NoA);
1408 return status;
1409}
1410
1411/**
1412 * hdd_setP2pOpps
1413 *
1414 *FUNCTION:
1415 * This function is called from hdd_hostapd_ioctl function when Driver
1416 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1417 *
1418 *LOGIC:
1419 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1420 *
1421 *ASSUMPTIONS:
1422 *
1423 *
1424 *NOTE:
1425 *
1426 * @param dev Pointer to net device structure
1427 * @param command Pointer to command
1428 *
1429 * @return Status
1430 */
1431
1432int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1433{
1434 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1435 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1436 VOS_STATUS status = VOS_STATUS_SUCCESS;
1437 tP2pPsConfig NoA;
1438 char *param;
1439 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001440 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001441
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001442 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001443 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301444 {
1445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1446 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001447 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301448 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001449 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001450 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1451 if (ret < 3)
1452 {
1453 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1454 "%s: P2P_SET GO PS: fail to read param "
1455 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1456 __func__, legacy_ps, opp_ps, ctwindow);
1457 return -EINVAL;
1458 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001459 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001460 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001461 __func__, legacy_ps, opp_ps, ctwindow);
1462
1463 /* PS Selection
1464 * Opportunistic Power Save (1)
1465 */
1466
1467 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1468 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301469 * values are coming from wpa_supplicant as -1.
1470 * Example : User want to set ctWindow with 30 then wpa_cli command :
1471 * P2P_SET ctwindow 30
1472 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001473 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301474 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001475 if (ctwindow != -1)
1476 {
1477
1478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001479 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001480 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1481
1482 if (ctwindow != pAdapter->ctw)
1483 {
1484 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301485
Jeff Johnson295189b2012-06-20 16:38:30 -07001486 if(pAdapter->ops)
1487 {
1488 NoA.opp_ps = pAdapter->ops;
1489 NoA.ctWindow = pAdapter->ctw;
1490 NoA.duration = 0;
1491 NoA.single_noa_duration = 0;
1492 NoA.interval = 0;
1493 NoA.count = 0;
1494 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1495 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301496
Jeff Johnson295189b2012-06-20 16:38:30 -07001497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1498 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1499 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001500 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001501 NoA.ctWindow, NoA.duration, NoA.interval,
1502 NoA.count, NoA.single_noa_duration,
1503 NoA.psSelection);
1504
1505 sme_p2pSetPs(hHal, &NoA);
1506 }
1507 return 0;
1508 }
1509 }
1510
1511 if (opp_ps != -1)
1512 {
1513 pAdapter->ops = opp_ps;
1514
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301515 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001516 {
1517 NoA.opp_ps = opp_ps;
1518 NoA.ctWindow = pAdapter->ctw;
1519 NoA.duration = 0;
1520 NoA.single_noa_duration = 0;
1521 NoA.interval = 0;
1522 NoA.count = 0;
1523 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1524 NoA.sessionid = pAdapter->sessionId;
1525
1526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1527 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1528 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001529 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001530 NoA.ctWindow, NoA.duration, NoA.interval,
1531 NoA.count, NoA.single_noa_duration,
1532 NoA.psSelection);
1533
1534 sme_p2pSetPs(hHal, &NoA);
1535 }
1536 }
1537 return status;
1538}
1539
1540int hdd_setP2pPs( struct net_device *dev, void *msgData )
1541{
1542 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1543 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1544 VOS_STATUS status = VOS_STATUS_SUCCESS;
1545 tP2pPsConfig NoA;
1546 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1547
1548 NoA.opp_ps = pappNoA->opp_ps;
1549 NoA.ctWindow = pappNoA->ctWindow;
1550 NoA.duration = pappNoA->duration;
1551 NoA.interval = pappNoA->interval;
1552 NoA.count = pappNoA->count;
1553 NoA.single_noa_duration = pappNoA->single_noa_duration;
1554 NoA.psSelection = pappNoA->psSelection;
1555 NoA.sessionid = pAdapter->sessionId;
1556
1557 sme_p2pSetPs(hHal, &NoA);
1558 return status;
1559}
Jeff Johnson295189b2012-06-20 16:38:30 -07001560
1561static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1562{
1563 tANI_U8 sessionType;
1564
1565 switch( type )
1566 {
1567 case NL80211_IFTYPE_AP:
1568 sessionType = WLAN_HDD_SOFTAP;
1569 break;
1570 case NL80211_IFTYPE_P2P_GO:
1571 sessionType = WLAN_HDD_P2P_GO;
1572 break;
1573 case NL80211_IFTYPE_P2P_CLIENT:
1574 sessionType = WLAN_HDD_P2P_CLIENT;
1575 break;
1576 case NL80211_IFTYPE_STATION:
1577 sessionType = WLAN_HDD_INFRA_STATION;
1578 break;
1579 case NL80211_IFTYPE_MONITOR:
1580 sessionType = WLAN_HDD_MONITOR;
1581 break;
1582 default:
1583 sessionType = WLAN_HDD_INFRA_STATION;
1584 break;
1585 }
1586
1587 return sessionType;
1588}
1589
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001590#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1591struct wireless_dev* wlan_hdd_add_virtual_intf(
1592 struct wiphy *wiphy, const char *name,
1593 enum nl80211_iftype type,
1594 u32 *flags, struct vif_params *params )
1595#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1596struct wireless_dev* wlan_hdd_add_virtual_intf(
1597 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1598 u32 *flags, struct vif_params *params )
1599#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001600struct net_device* wlan_hdd_add_virtual_intf(
1601 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1602 u32 *flags, struct vif_params *params )
1603#else
1604int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1605 enum nl80211_iftype type,
1606 u32 *flags, struct vif_params *params )
1607#endif
1608{
1609 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301610 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301611 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001612 ENTER();
1613
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301614 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1615 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301616 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1617 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1618 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001619 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001620 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001621 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05301622#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1623 return ERR_PTR(-EINVAL);
1624#else
1625 return -EAGAIN;
1626#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001627 }
1628
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001629 if (pHddCtx->isLogpInProgress)
1630 {
1631 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1632 "%s:LOGP in Progress. Ignore!!!", __func__);
1633#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301634 return ERR_PTR(-EINVAL);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001635#else
1636 return -EAGAIN;
1637#endif
1638 }
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301639
1640 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1641 pScanInfo = &pHddCtx->scan_info;
1642 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1643 (pHddCtx->scan_info.mScanPending))
1644 {
1645 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1646 eCSR_SCAN_ABORT_DEFAULT);
1647 hddLog(VOS_TRACE_LEVEL_INFO,
1648 "%s: Abort Scan while adding virtual interface",__func__);
1649 }
1650
1651 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05301652 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1653 ((NL80211_IFTYPE_P2P_GO == type) ||
1654 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001655 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001656 /* Generate the P2P Interface Address. this address must be
1657 * different from the P2P Device Address.
1658 */
1659 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1660 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301661 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001662 wlan_hdd_get_session_type(type),
1663 name, p2pDeviceAddress.bytes,
1664 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001665 }
1666 else
1667 {
1668 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1669 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1670 }
1671
1672 if( NULL == pAdapter)
1673 {
1674 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1675#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301676 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001677#else
1678 return -EINVAL;
1679#endif
1680 }
1681 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001682#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1683 return pAdapter->dev->ieee80211_ptr;
1684#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001685 return pAdapter->dev;
1686#else
1687 return 0;
1688#endif
1689}
1690
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001691#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1692int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1693#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001694int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001695#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001696{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001697#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1698 struct net_device *dev = wdev->netdev;
1699#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301700 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301701 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301702 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1703 int status;
1704 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001705
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301706 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1707 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1708 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301709 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1710 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001711
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301712 status = wlan_hdd_validate_context(pHddCtx);
1713
1714 if (0 != status)
1715 {
1716 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1717 "%s: HDD context is not valid", __func__);
1718 return status;
1719 }
1720
1721 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001722 pVirtAdapter->macAddressCurrent.bytes );
1723
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05301724 hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301725 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1726 EXIT();
1727 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001728}
1729
1730void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001731 tANI_U32 nFrameLength,
1732 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301733 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07001734{
1735 //Indicate a Frame over Monitor Intf.
1736 int rxstat;
1737 struct sk_buff *skb = NULL;
1738 int needed_headroom = 0;
1739 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1740 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001741#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001742#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1743 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1744#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001745#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001746 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1747
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001748 if (NULL == pbFrames)
1749 {
1750 hddLog(LOGE, FL("NULL frame pointer"));
1751 return;
1752 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001753
1754 /* room for the radiotap header based on driver features
1755 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1756 * RX flags.
1757 * */
1758 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1759
1760 //alloc skb here
1761 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1762 if (unlikely(NULL == skb))
1763 {
1764 hddLog( LOGW, FL("Unable to allocate skb"));
1765 return;
1766 }
1767 skb_reserve(skb, VPKT_SIZE_BUFFER);
1768 if (unlikely(skb_headroom(skb) < nFrameLength))
1769 {
1770 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1771 "HDD [%d]: Insufficient headroom, "
1772 "head[%p], data[%p], req[%d]",
1773 __LINE__, skb->head, skb->data, nFrameLength);
1774 kfree_skb(skb);
1775 return ;
1776 }
1777 // actually push the data
1778 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1779 /* prepend radiotap information */
1780 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1781 {
1782 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1783 //free skb
1784 kfree_skb(skb);
1785 return ;
1786 }
1787
1788 skb_reset_mac_header( skb );
1789 skb->dev = pMonAdapter->dev;
1790 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001791 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001792#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001793#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001794 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001795#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001796#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001797 rxstat = netif_rx_ni(skb);
1798 if( NET_RX_SUCCESS == rxstat )
1799 {
1800 hddLog( LOG1, FL("Success"));
1801 }
1802 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301803 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07001804
1805 return ;
1806}
1807
1808void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301809 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07001810 tANI_U8* pbFrames,
1811 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301812 tANI_U32 rxChan,
1813 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001814{
1815 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301816 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07001817 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001818 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001819 tActionFrmType actionFrmType;
1820 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301821 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05301822 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301823 VOS_STATUS status;
1824 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001825
Arif Hussain6d2a3322013-11-17 19:50:10 -08001826 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001827 __func__, frameType, nFrameLength);
1828
1829 if (NULL == pAdapter)
1830 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001831 hddLog(LOGE, FL("pAdapter is NULL"));
1832 return;
1833 }
1834
1835 if (0 == nFrameLength)
1836 {
1837 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
1838 return;
1839 }
1840
1841 if (NULL == pbFrames)
1842 {
1843 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001844 return;
1845 }
1846
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001847 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1848 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1849
1850 /* Get pAdapter from Destination mac address of the frame */
1851 if ((type == SIR_MAC_MGMT_FRAME) &&
1852 (subType != SIR_MAC_MGMT_PROBE_REQ))
1853 {
1854 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1855 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1856 if (NULL == pAdapter)
1857 {
1858 /* Under assumtion that we don't receive any action frame
1859 * with BCST as destination we dropping action frame
1860 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001861 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1862 MAC_ADDRESS_STR ,
1863 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1864 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08001865 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001866 return;
1867 }
1868 }
1869
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001870
Jeff Johnson295189b2012-06-20 16:38:30 -07001871 if (NULL == pAdapter->dev)
1872 {
1873 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1874 return;
1875 }
1876
1877 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1878 {
1879 hddLog( LOGE, FL("pAdapter has invalid magic"));
1880 return;
1881 }
1882
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301883 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1884 if (NULL == pHddCtx)
1885 {
1886 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
1887 return;
1888 }
1889
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001890 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1891 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001892 {
1893 hdd_adapter_t *pMonAdapter =
1894 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1895
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001896 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001897 {
1898 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1899 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1900 pbFrames, frameType);
1901 return;
1902 }
1903 }
1904
1905 //Channel indicated may be wrong. TODO
1906 //Indicate an action frame.
1907 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1908 {
1909 freq = ieee80211_channel_to_frequency( rxChan,
1910 IEEE80211_BAND_2GHZ);
1911 }
1912 else
1913 {
1914 freq = ieee80211_channel_to_frequency( rxChan,
1915 IEEE80211_BAND_5GHZ);
1916 }
1917
Jeff Johnsone7245742012-09-05 17:12:55 -07001918 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301919 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301920
1921 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001922 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001923 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001924 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1925 {
1926 // public action frame
1927 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001928 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 -08001929 // P2P action frames
1930 {
1931 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08001932 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001933#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001934 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1935 {
1936 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1937 actionFrmType);
1938 }
1939 else
1940 {
1941 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1942 p2p_action_frame_type[actionFrmType]);
1943 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1944 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1945 {
1946 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1947 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001948 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001949 }
1950 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1951 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1952 {
1953 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001954 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1955 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001956 }
1957 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1958 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1959 {
1960 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1961 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1962 " completed state Autonomous GO formation");
1963 }
1964 }
1965#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301966 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
1967 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
1968 {
1969 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1970 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
1971 actionFrmType == WLAN_HDD_INVITATION_REQ ||
1972 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
1973 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
1974 {
1975 hddLog( LOG1, "Extend RoC timer on reception of"
1976 " Action Frame");
1977 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
1978 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
1979 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
1980 else
1981 extend_time = ACTION_FRAME_DEFAULT_WAIT;
1982 if (completion_done(&pAdapter->rem_on_chan_ready_event))
1983 {
1984 vos_timer_stop(
1985 &pRemainChanCtx->hdd_remain_on_chan_timer);
1986 status = vos_timer_start(
1987 &pRemainChanCtx->hdd_remain_on_chan_timer,
1988 extend_time);
1989 if (status != VOS_STATUS_SUCCESS)
1990 {
1991 hddLog( LOGE, "ROC timer start failed");
1992 }
1993 }
1994 else
1995 {
1996 // Buffer Packet
1997 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
1998 {
1999 pRemainChanCtx->action_pkt_buff.frame_length =
2000 nFrameLength;
2001 pRemainChanCtx->action_pkt_buff.freq = freq;
2002 pRemainChanCtx->action_pkt_buff.frame_ptr
2003 = vos_mem_malloc(nFrameLength);
2004 vos_mem_copy(
2005 pRemainChanCtx->action_pkt_buff.frame_ptr,
2006 pbFrames, nFrameLength);
2007 hddLog( LOGE,"%s:"
2008 "Action Pkt Cached successfully !!!", __func__);
2009 }
2010 else
2011 {
2012 hddLog( LOGE,"%s:"
2013 "Frames are pending. dropping frame !!!",
2014 __func__);
2015 }
2016 return;
2017 }
2018 }
2019 }
2020 if (pRemainChanCtx != NULL &&
2021 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2022 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2023 hddLog( LOG1, "%s:"
2024 "Rcvd action frame after timer expired ", __func__);
2025
2026 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) ||
2027 (actionFrmType == WLAN_HDD_GO_NEG_REQ) ||
2028 (actionFrmType == WLAN_HDD_INVITATION_REQ) )
2029 {
2030 pScanInfo = &pHddCtx->scan_info;
2031 if((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2032 {
2033 hddLog(LOGE,"Action frame received when Scanning is in"
2034 " progress. Abort Scan.");
2035 hdd_abort_mac_scan(pAdapter->pHddCtx,
2036 pAdapter->sessionId,
2037 eCSR_SCAN_ABORT_DEFAULT);
2038 }
2039 }
2040 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2041 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2042 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2043 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2044 {
2045 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2046 __func__);
2047 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002048 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002049 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002050#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002051 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 -07002052 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002053 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
2054#ifdef WLAN_FEATURE_TDLS_DEBUG
2055 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2056 MAC_ADDR_ARRAY(mac),rxRssi);
2057#endif
2058 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2059 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002060 }
2061#endif
2062 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002063#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002064 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2065 {
2066 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2067 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2068 {
2069 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2070 actionFrmType);
2071 }
2072 else
2073 {
2074 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2075 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002076 }
2077 }
2078#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002079 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2080 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2081 {
Kumar Anand82c009f2014-05-29 00:29:42 -07002082 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
2083 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002084 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002085 }
2086
Jeff Johnson295189b2012-06-20 16:38:30 -07002087 //Indicate Frame Over Normal Interface
2088 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2089
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002090#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2091 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2092 pbFrames, nFrameLength,
2093 GFP_ATOMIC );
2094#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002095 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2096 pbFrames, nFrameLength,
2097 GFP_ATOMIC );
2098#else
2099 cfg80211_rx_mgmt( pAdapter->dev, freq,
2100 pbFrames, nFrameLength,
2101 GFP_ATOMIC );
2102#endif //LINUX_VERSION_CODE
2103}
2104
2105/*
2106 * ieee80211_add_rx_radiotap_header - add radiotap header
2107 */
2108static int hdd_wlan_add_rx_radiotap_hdr (
2109 struct sk_buff *skb, int rtap_len, int flag )
2110{
2111 u8 rtap_temp[20] = {0};
2112 struct ieee80211_radiotap_header *rthdr;
2113 unsigned char *pos;
2114 u16 rx_flags = 0;
2115
2116 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2117
2118 /* radiotap header, set always present flags */
2119 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2120 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2121 rthdr->it_len = cpu_to_le16(rtap_len);
2122
2123 pos = (unsigned char *) (rthdr + 1);
2124
2125 /* the order of the following fields is important */
2126
2127 /* IEEE80211_RADIOTAP_FLAGS */
2128 *pos = 0;
2129 pos++;
2130
2131 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2132 /* ensure 2 byte alignment for the 2 byte field as required */
2133 if ((pos - (u8 *)rthdr) & 1)
2134 pos++;
2135 put_unaligned_le16(rx_flags, pos);
2136 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302137
Jeff Johnson295189b2012-06-20 16:38:30 -07002138 // actually push the data
2139 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2140
2141 return 0;
2142}
2143
2144static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2145 hdd_cfg80211_state_t* cfgState,
2146 tANI_BOOLEAN actionSendSuccess )
2147{
2148 struct ieee80211_radiotap_header *rthdr;
2149 unsigned char *pos;
2150 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002151#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002152#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2153 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2154#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002155#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002156
2157 /* 2 Byte for TX flags and 1 Byte for Retry count */
2158 u32 rtHdrLen = sizeof(*rthdr) + 3;
2159
2160 u8 *data;
2161
2162 /* We have to return skb with Data starting with MAC header. We have
2163 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2164 * entire skb->len from skb and then we will push cfgState->buf to skb
2165 * */
2166 if( NULL == skb_pull(skb, skb->len) )
2167 {
2168 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2169 kfree_skb(cfgState->skb);
2170 return;
2171 }
2172
2173 data = skb_push( skb, cfgState->len );
2174
2175 if (data == NULL)
2176 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002177 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002178 kfree_skb( cfgState->skb );
2179 return;
2180 }
2181
2182 memcpy( data, cfgState->buf, cfgState->len );
2183
2184 /* send frame to monitor interfaces now */
2185 if( skb_headroom(skb) < rtHdrLen )
2186 {
2187 hddLog( LOGE, FL("No headroom for rtap header"));
2188 kfree_skb(cfgState->skb);
2189 return;
2190 }
2191
2192 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2193
2194 memset( rthdr, 0, rtHdrLen );
2195 rthdr->it_len = cpu_to_le16( rtHdrLen );
2196 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2197 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2198 );
2199
2200 pos = (unsigned char *)( rthdr+1 );
2201
2202 // Fill TX flags
2203 *pos = actionSendSuccess;
2204 pos += 2;
2205
2206 // Fill retry count
2207 *pos = 0;
2208 pos++;
2209
2210 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002211 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002212 skb->pkt_type = PACKET_OTHERHOST;
2213 skb->protocol = htons(ETH_P_802_2);
2214 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002215#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002216#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002217 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002218#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002219#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002220 if (in_interrupt())
2221 netif_rx( skb );
2222 else
2223 netif_rx_ni( skb );
2224
2225 /* Enable Queues which we have disabled earlier */
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302226 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002227
2228}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302229