blob: b73904f5af140ba49c1ed5d1b6ea3fbab5a344f3 [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;
Chet Lanctot186b5732013-03-18 10:26:30 -0700882#ifdef WLAN_FEATURE_11W
883 tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit
884#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700885
Jeff Johnson295189b2012-06-20 16:38:30 -0700886#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
887 hdd_adapter_t *goAdapter;
888#endif
Sushant Kaushik10728722014-05-14 16:20:25 +0530889 if (NULL == pAdapter)
890 {
891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
892 "%s: HDD adapter context is Null", __func__);
893 return -ENODEV;
894 }
895 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530896 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
897 pAdapter->device_mode ));
Sushant Kaushik10728722014-05-14 16:20:25 +0530898 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
899 if (NULL == cfgState)
900 {
901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
902 "%s: cfg state is Null", __func__);
903 return -ENODEV;
904 }
905 pRemainChanCtx = cfgState->remain_on_chan_ctx;
906 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530907 status = wlan_hdd_validate_context(pHddCtx);
908
909 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800910 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530911 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
912 "%s: HDD context is not valid", __func__);
913 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800914 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530915
c_hpothu7f63e882013-10-02 19:13:35 +0530916 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
917 __func__, pAdapter->device_mode, type);
918
919
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700920#ifdef WLAN_FEATURE_P2P_DEBUG
921 if ((type == SIR_MAC_MGMT_FRAME) &&
922 (subType == SIR_MAC_MGMT_ACTION) &&
923 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
924 {
925 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800926 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700927 {
928 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
929 actionFrmType);
930 }
931 else
932 {
933 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
934 p2p_action_frame_type[actionFrmType]);
935 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
936 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
937 {
938 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
939 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800940 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700941 }
942 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
943 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
944 {
945 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
946 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
947 " completed state");
948 }
949 }
950 }
951#endif
952
Jeff Johnsone7245742012-09-05 17:12:55 -0700953#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
954 noack = dont_wait_for_ack;
955#endif
956
957 //If the wait is coming as 0 with off channel set
958 //then set the wait to 200 ms
959 if (offchan && !wait)
960 wait = ACTION_FRAME_DEFAULT_WAIT;
961
Jeff Johnson295189b2012-06-20 16:38:30 -0700962 //Call sme API to send out a action frame.
963 // OR can we send it directly through data path??
964 // After tx completion send tx status back.
965 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
966 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
967 )
968 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700969 if (type == SIR_MAC_MGMT_FRAME)
970 {
971 if (subType == SIR_MAC_MGMT_PROBE_RSP)
972 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530973 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -0700974 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530975 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700976 goto err_rem_channel;
977 }
978 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
979 (subType == SIR_MAC_MGMT_DEAUTH))
980 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700981 /* During EAP failure or P2P Group Remove supplicant
982 * is sending del_station command to driver. From
983 * del_station function, Driver will send deauth frame to
984 * p2p client. No need to send disassoc frame from here.
985 * so Drop the frame here and send tx indication back to
986 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700987 */
988 tANI_U8 dstMac[ETH_ALEN] = {0};
989 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700990 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700991 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -0800992 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -0700993 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -0800994 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 goto err_rem_channel;
996 }
997 }
998 }
999
1000 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001001 {
1002 if ( !noack )
1003 {
1004 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1005 __func__);
1006 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1007 }
1008 else
1009 {
1010 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1011 __func__);
1012 return -EBUSY;
1013 }
1014 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001015
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301016 if( subType == SIR_MAC_MGMT_ACTION)
1017 {
1018 hddLog( LOG1, "Action frame tx request : %s",
1019 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1020 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001021
1022#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1023 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1024
1025 //If GO adapter exists and operating on same frequency
1026 //then we will not request remain on channel
1027 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1028 == goAdapter->sessionCtx.ap.operatingChannel ) )
1029 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301030 /* if GO exist and is not off channel
1031 * wait time should be zero.
1032 */
1033 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001034 goto send_frame;
1035 }
1036#endif
1037
1038#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1039 if( offchan && wait)
1040 {
1041 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301042 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001043 // In case of P2P Client mode if we are already
1044 // on the same channel then send the frame directly
1045
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301046 if( (cfgState->remain_on_chan_ctx != NULL) &&
1047 (cfgState->current_freq == chan->center_freq)
1048 )
1049 {
1050 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1051 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301052 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301053 /* Some times FW is taking almost 500 msec for
1054 * full 15 retries, which leads to ROC expiration
1055 * by the time peer gets response from other peer.
1056 * Therefore as part of temporary fix , in host
1057 * ROC time is extended. For frames where we are
1058 * expecting response from peer , its extended by
1059 * 500 msec to make ROC wait time as 1 sec and
1060 * in other cases its extended by 300 msec to make
1061 * total ROC wait as 500 msec.
1062 * TODO: FW needs to fix as why 15 retry is taking
1063 * such long time.
1064 */
1065 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1066 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1067 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1068 wait = wait + ACTION_FRAME_RSP_WAIT;
1069 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1070 actionFrmType == WLAN_HDD_INVITATION_RESP )
1071 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301072 vos_timer_stop(
1073 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1074 status = vos_timer_start(
1075 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1076 wait);
1077 if ( status != VOS_STATUS_SUCCESS )
vamsida0e5ab2013-12-26 14:33:27 +05301078 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301079 hddLog( LOGE, "Remain on Channel timer start failed");
1080 }
1081
1082 hddLog(VOS_TRACE_LEVEL_INFO,
1083 "action frame: extending the wait time %u",
1084 wait);
1085 goto send_frame;
1086 }
1087 else
1088 {
1089 if ( TRUE ==
1090 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1091 {
1092 hddLog(VOS_TRACE_LEVEL_INFO,
1093 "action frame tx: waiting for completion of ROC ");
1094
1095 status = wait_for_completion_interruptible_timeout(
1096 &pAdapter->cancel_rem_on_chan_var,
1097 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1098 if (0 >= status)
1099 {
1100 hddLog( LOGE,
1101 "%s:wait on cancel_rem_on_chan_var failed %d",
1102 __func__, status);
1103 }
vamsida0e5ab2013-12-26 14:33:27 +05301104 }
1105 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301106 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301107 hddLog(VOS_TRACE_LEVEL_INFO,
1108 "action frame: Request ROC for wait time %u", wait);
1109
Jeff Johnson295189b2012-06-20 16:38:30 -07001110 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001111 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001112 chan,
1113#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1114 channel_type,
1115#endif
1116 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301117 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001118
1119 if(0 != status)
1120 {
1121 if( (-EBUSY == status) &&
1122 (cfgState->current_freq == chan->center_freq) )
1123 {
1124 goto send_frame;
1125 }
1126 goto err_rem_channel;
1127 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001128 /* Wait for driver to be ready on the requested channel */
1129 status = wait_for_completion_interruptible_timeout(
1130 &pAdapter->offchannel_tx_event,
1131 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301132 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001133 {
c_hpothu7f63e882013-10-02 19:13:35 +05301134 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001135 goto err_rem_channel;
1136 }
1137 }
1138 else if ( offchan )
1139 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001140 /* Check before sending action frame
1141 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001142 if(NULL == cfgState->remain_on_chan_ctx)
1143 {
1144 goto err_rem_channel;
1145 }
1146 }
1147 send_frame:
1148#endif
1149
Jeff Johnsone7245742012-09-05 17:12:55 -07001150 if(!noack)
1151 {
1152 cfgState->buf = vos_mem_malloc( len ); //buf;
1153 if( cfgState->buf == NULL )
1154 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001155
Jeff Johnsone7245742012-09-05 17:12:55 -07001156 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001157
Jeff Johnsone7245742012-09-05 17:12:55 -07001158 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001159
1160#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001161 if( cfgState->remain_on_chan_ctx )
1162 {
1163 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1164 *cookie = cfgState->action_cookie;
1165 }
1166 else
1167 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001168#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001169 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001170 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001171#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001172 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001173#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301174 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001175
1176 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001177 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1178 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 )
1180 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001181 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001182
Jeff Johnsone7245742012-09-05 17:12:55 -07001183 if ((type == SIR_MAC_MGMT_FRAME) &&
1184 (subType == SIR_MAC_MGMT_ACTION) &&
1185 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001186 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001187 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301188 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001189 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001190 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001191 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301192 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001193 }
1194 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1195 {
1196 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301197 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001198 }
1199 }
Chet Lanctot186b5732013-03-18 10:26:30 -07001200#ifdef WLAN_FEATURE_11W
1201 if ((type == SIR_MAC_MGMT_FRAME) &&
1202 (subType == SIR_MAC_MGMT_ACTION) &&
1203 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME))
1204 {
1205 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1206 "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query");
1207 // Since this is an SA Query Action Frame, we have to protect it
1208 WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]);
1209 }
1210#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001211 if (eHAL_STATUS_SUCCESS !=
1212 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301213 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001214 {
1215 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1216 "%s: sme_sendAction returned fail", __func__);
1217 goto err;
1218 }
1219 }
1220 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1221 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1222 )
1223 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001224 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001225 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001226 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001227 {
1228 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1229 "%s: WLANSAP_SendAction returned fail", __func__);
1230 goto err;
1231 }
1232 }
1233
1234 return 0;
1235err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001236 if(!noack)
1237 {
1238 hdd_sendActionCnf( pAdapter, FALSE );
1239 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001240 return 0;
1241err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001242 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001243 cfg80211_mgmt_tx_status(
1244#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1245 pAdapter->dev->ieee80211_ptr,
1246#else
1247 pAdapter->dev,
1248#endif
1249 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001250 return 0;
1251}
1252
1253#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001254#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1255int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1256 struct wireless_dev *wdev,
1257 u64 cookie)
1258{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301259 u64 cookie_dummy;
1260 cookie_dummy = cookie << 32;
1261 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1262 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001263 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1264}
1265#else
1266int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001267 struct net_device *dev,
1268 u64 cookie)
1269{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301270 u64 cookie_dummy;
1271 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1272 cookie_dummy = cookie << 32;
1273 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1274 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1275 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001276 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1277}
1278#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001279#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001280
1281void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1282{
1283 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1284
Jeff Johnsone7245742012-09-05 17:12:55 -07001285 cfgState->actionFrmState = HDD_IDLE;
1286
Jeff Johnson295189b2012-06-20 16:38:30 -07001287 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1288 if( NULL == cfgState->buf )
1289 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001290 return;
1291 }
1292
1293 /* If skb is NULL it means this packet was received on CFG80211 interface
1294 * else it was received on Monitor interface */
1295 if( cfgState->skb == NULL )
1296 {
1297 /*
1298 * buf is the same pointer it passed us to send. Since we are sending
1299 * it through control path, we use different buffers.
1300 * In case of mac80211, they just push it to the skb and pass the same
1301 * data while sending tx ack status.
1302 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001303 cfg80211_mgmt_tx_status(
1304#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1305 pAdapter->dev->ieee80211_ptr,
1306#else
1307 pAdapter->dev,
1308#endif
1309 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001310 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1311 vos_mem_free( cfgState->buf );
1312 cfgState->buf = NULL;
1313 }
1314 else
1315 {
1316 hdd_adapter_t* pMonAdapter =
1317 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1318 if( pMonAdapter == NULL )
1319 {
1320 hddLog( LOGE, "Not able to get Monitor Adapter");
1321 cfgState->skb = NULL;
1322 vos_mem_free( cfgState->buf );
1323 cfgState->buf = NULL;
1324 complete(&pAdapter->tx_action_cnf_event);
1325 return;
1326 }
1327 /* Send TX completion feedback over monitor interface. */
1328 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1329 cfgState->skb = NULL;
1330 vos_mem_free( cfgState->buf );
1331 cfgState->buf = NULL;
1332 /* Look for the next Mgmt packet to TX */
1333 hdd_mon_tx_mgmt_pkt(pAdapter);
1334 }
1335 complete(&pAdapter->tx_action_cnf_event);
1336}
1337
1338/**
1339 * hdd_setP2pNoa
1340 *
1341 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301342 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001343 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1344 *
1345 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301346 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001347 *
1348 *ASSUMPTIONS:
1349 *
1350 *
1351 *NOTE:
1352 *
1353 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301354 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001355 *
1356 * @return Status
1357 */
1358
1359int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1360{
1361 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1362 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1363 VOS_STATUS status = VOS_STATUS_SUCCESS;
1364 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001365 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001366 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001367 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001368
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001369 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001370 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301371 {
1372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1373 "%s: strnchr failed to find delimeter",__func__);
1374 return -EINVAL;
1375 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001376 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001377 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1378 if (ret < 3)
1379 {
1380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1381 "%s: P2P_SET GO NoA: fail to read param "
1382 "count=%d duration=%d interval=%d \n",
1383 __func__, count, start_time, duration);
1384 return -EINVAL;
1385 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001386 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001387 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001388 __func__, count, start_time, duration);
1389 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001390 /* PS Selection
1391 * Periodic NoA (2)
1392 * Single NOA (4)
1393 */
1394 NoA.opp_ps = 0;
1395 NoA.ctWindow = 0;
1396 if (count == 1)
1397 {
1398 NoA.duration = 0;
1399 NoA.single_noa_duration = duration;
1400 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1401 }
1402 else
1403 {
1404 NoA.duration = duration;
1405 NoA.single_noa_duration = 0;
1406 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1407 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001408 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001409 NoA.count = count;
1410 NoA.sessionid = pAdapter->sessionId;
1411
1412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1413 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1414 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001415 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001416 NoA.ctWindow, NoA.duration, NoA.interval,
1417 NoA.count, NoA.single_noa_duration,
1418 NoA.psSelection);
1419
1420 sme_p2pSetPs(hHal, &NoA);
1421 return status;
1422}
1423
1424/**
1425 * hdd_setP2pOpps
1426 *
1427 *FUNCTION:
1428 * This function is called from hdd_hostapd_ioctl function when Driver
1429 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1430 *
1431 *LOGIC:
1432 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1433 *
1434 *ASSUMPTIONS:
1435 *
1436 *
1437 *NOTE:
1438 *
1439 * @param dev Pointer to net device structure
1440 * @param command Pointer to command
1441 *
1442 * @return Status
1443 */
1444
1445int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1446{
1447 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1448 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1449 VOS_STATUS status = VOS_STATUS_SUCCESS;
1450 tP2pPsConfig NoA;
1451 char *param;
1452 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001453 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001454
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001455 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001456 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301457 {
1458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1459 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001460 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301461 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001462 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001463 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1464 if (ret < 3)
1465 {
1466 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1467 "%s: P2P_SET GO PS: fail to read param "
1468 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1469 __func__, legacy_ps, opp_ps, ctwindow);
1470 return -EINVAL;
1471 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001472 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001473 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001474 __func__, legacy_ps, opp_ps, ctwindow);
1475
1476 /* PS Selection
1477 * Opportunistic Power Save (1)
1478 */
1479
1480 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1481 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301482 * values are coming from wpa_supplicant as -1.
1483 * Example : User want to set ctWindow with 30 then wpa_cli command :
1484 * P2P_SET ctwindow 30
1485 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001486 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301487 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001488 if (ctwindow != -1)
1489 {
1490
1491 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001492 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001493 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1494
1495 if (ctwindow != pAdapter->ctw)
1496 {
1497 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301498
Jeff Johnson295189b2012-06-20 16:38:30 -07001499 if(pAdapter->ops)
1500 {
1501 NoA.opp_ps = pAdapter->ops;
1502 NoA.ctWindow = pAdapter->ctw;
1503 NoA.duration = 0;
1504 NoA.single_noa_duration = 0;
1505 NoA.interval = 0;
1506 NoA.count = 0;
1507 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1508 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301509
Jeff Johnson295189b2012-06-20 16:38:30 -07001510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1511 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1512 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001513 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001514 NoA.ctWindow, NoA.duration, NoA.interval,
1515 NoA.count, NoA.single_noa_duration,
1516 NoA.psSelection);
1517
1518 sme_p2pSetPs(hHal, &NoA);
1519 }
1520 return 0;
1521 }
1522 }
1523
1524 if (opp_ps != -1)
1525 {
1526 pAdapter->ops = opp_ps;
1527
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301528 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001529 {
1530 NoA.opp_ps = opp_ps;
1531 NoA.ctWindow = pAdapter->ctw;
1532 NoA.duration = 0;
1533 NoA.single_noa_duration = 0;
1534 NoA.interval = 0;
1535 NoA.count = 0;
1536 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1537 NoA.sessionid = pAdapter->sessionId;
1538
1539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1540 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1541 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001542 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001543 NoA.ctWindow, NoA.duration, NoA.interval,
1544 NoA.count, NoA.single_noa_duration,
1545 NoA.psSelection);
1546
1547 sme_p2pSetPs(hHal, &NoA);
1548 }
1549 }
1550 return status;
1551}
1552
1553int hdd_setP2pPs( struct net_device *dev, void *msgData )
1554{
1555 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1556 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1557 VOS_STATUS status = VOS_STATUS_SUCCESS;
1558 tP2pPsConfig NoA;
1559 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1560
1561 NoA.opp_ps = pappNoA->opp_ps;
1562 NoA.ctWindow = pappNoA->ctWindow;
1563 NoA.duration = pappNoA->duration;
1564 NoA.interval = pappNoA->interval;
1565 NoA.count = pappNoA->count;
1566 NoA.single_noa_duration = pappNoA->single_noa_duration;
1567 NoA.psSelection = pappNoA->psSelection;
1568 NoA.sessionid = pAdapter->sessionId;
1569
1570 sme_p2pSetPs(hHal, &NoA);
1571 return status;
1572}
Jeff Johnson295189b2012-06-20 16:38:30 -07001573
1574static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1575{
1576 tANI_U8 sessionType;
1577
1578 switch( type )
1579 {
1580 case NL80211_IFTYPE_AP:
1581 sessionType = WLAN_HDD_SOFTAP;
1582 break;
1583 case NL80211_IFTYPE_P2P_GO:
1584 sessionType = WLAN_HDD_P2P_GO;
1585 break;
1586 case NL80211_IFTYPE_P2P_CLIENT:
1587 sessionType = WLAN_HDD_P2P_CLIENT;
1588 break;
1589 case NL80211_IFTYPE_STATION:
1590 sessionType = WLAN_HDD_INFRA_STATION;
1591 break;
1592 case NL80211_IFTYPE_MONITOR:
1593 sessionType = WLAN_HDD_MONITOR;
1594 break;
1595 default:
1596 sessionType = WLAN_HDD_INFRA_STATION;
1597 break;
1598 }
1599
1600 return sessionType;
1601}
1602
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001603#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1604struct wireless_dev* wlan_hdd_add_virtual_intf(
1605 struct wiphy *wiphy, const char *name,
1606 enum nl80211_iftype type,
1607 u32 *flags, struct vif_params *params )
1608#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1609struct wireless_dev* wlan_hdd_add_virtual_intf(
1610 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1611 u32 *flags, struct vif_params *params )
1612#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001613struct net_device* wlan_hdd_add_virtual_intf(
1614 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1615 u32 *flags, struct vif_params *params )
1616#else
1617int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1618 enum nl80211_iftype type,
1619 u32 *flags, struct vif_params *params )
1620#endif
1621{
1622 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301623 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301624 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001625 ENTER();
1626
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301627 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1628 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301629 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1630 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1631 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001632 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001633 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001634 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05301635#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1636 return ERR_PTR(-EINVAL);
1637#else
1638 return -EAGAIN;
1639#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001640 }
1641
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001642 if (pHddCtx->isLogpInProgress)
1643 {
1644 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1645 "%s:LOGP in Progress. Ignore!!!", __func__);
1646#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301647 return ERR_PTR(-EINVAL);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001648#else
1649 return -EAGAIN;
1650#endif
1651 }
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301652
1653 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1654 pScanInfo = &pHddCtx->scan_info;
1655 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1656 (pHddCtx->scan_info.mScanPending))
1657 {
1658 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1659 eCSR_SCAN_ABORT_DEFAULT);
1660 hddLog(VOS_TRACE_LEVEL_INFO,
1661 "%s: Abort Scan while adding virtual interface",__func__);
1662 }
1663
1664 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05301665 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1666 ((NL80211_IFTYPE_P2P_GO == type) ||
1667 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001668 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001669 /* Generate the P2P Interface Address. this address must be
1670 * different from the P2P Device Address.
1671 */
1672 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1673 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301674 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001675 wlan_hdd_get_session_type(type),
1676 name, p2pDeviceAddress.bytes,
1677 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001678 }
1679 else
1680 {
1681 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1682 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1683 }
1684
1685 if( NULL == pAdapter)
1686 {
1687 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1688#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301689 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001690#else
1691 return -EINVAL;
1692#endif
1693 }
1694 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001695#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1696 return pAdapter->dev->ieee80211_ptr;
1697#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001698 return pAdapter->dev;
1699#else
1700 return 0;
1701#endif
1702}
1703
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001704#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1705int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1706#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001707int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001708#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001709{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001710#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1711 struct net_device *dev = wdev->netdev;
1712#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301713 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301714 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301715 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1716 int status;
1717 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001718
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301719 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1720 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1721 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301722 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1723 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001724
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301725 status = wlan_hdd_validate_context(pHddCtx);
1726
1727 if (0 != status)
1728 {
1729 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1730 "%s: HDD context is not valid", __func__);
1731 return status;
1732 }
1733
1734 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001735 pVirtAdapter->macAddressCurrent.bytes );
1736
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301737 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1738 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1739 EXIT();
1740 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001741}
1742
1743void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001744 tANI_U32 nFrameLength,
1745 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301746 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07001747{
1748 //Indicate a Frame over Monitor Intf.
1749 int rxstat;
1750 struct sk_buff *skb = NULL;
1751 int needed_headroom = 0;
1752 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1753 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001754#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001755#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1756 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1757#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001758#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001759 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1760
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001761 if (NULL == pbFrames)
1762 {
1763 hddLog(LOGE, FL("NULL frame pointer"));
1764 return;
1765 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001766
1767 /* room for the radiotap header based on driver features
1768 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1769 * RX flags.
1770 * */
1771 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1772
1773 //alloc skb here
1774 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1775 if (unlikely(NULL == skb))
1776 {
1777 hddLog( LOGW, FL("Unable to allocate skb"));
1778 return;
1779 }
1780 skb_reserve(skb, VPKT_SIZE_BUFFER);
1781 if (unlikely(skb_headroom(skb) < nFrameLength))
1782 {
1783 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1784 "HDD [%d]: Insufficient headroom, "
1785 "head[%p], data[%p], req[%d]",
1786 __LINE__, skb->head, skb->data, nFrameLength);
1787 kfree_skb(skb);
1788 return ;
1789 }
1790 // actually push the data
1791 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1792 /* prepend radiotap information */
1793 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1794 {
1795 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1796 //free skb
1797 kfree_skb(skb);
1798 return ;
1799 }
1800
1801 skb_reset_mac_header( skb );
1802 skb->dev = pMonAdapter->dev;
1803 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001804 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001805#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001806#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001807 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001808#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001809#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001810 rxstat = netif_rx_ni(skb);
1811 if( NET_RX_SUCCESS == rxstat )
1812 {
1813 hddLog( LOG1, FL("Success"));
1814 }
1815 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301816 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07001817
1818 return ;
1819}
1820
1821void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301822 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07001823 tANI_U8* pbFrames,
1824 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301825 tANI_U32 rxChan,
1826 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001827{
1828 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301829 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07001830 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001831 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001832 tActionFrmType actionFrmType;
1833 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301834 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05301835 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301836 VOS_STATUS status;
1837 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001838
Arif Hussain6d2a3322013-11-17 19:50:10 -08001839 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001840 __func__, frameType, nFrameLength);
1841
1842 if (NULL == pAdapter)
1843 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001844 hddLog(LOGE, FL("pAdapter is NULL"));
1845 return;
1846 }
1847
1848 if (0 == nFrameLength)
1849 {
1850 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
1851 return;
1852 }
1853
1854 if (NULL == pbFrames)
1855 {
1856 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001857 return;
1858 }
1859
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001860 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1861 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1862
1863 /* Get pAdapter from Destination mac address of the frame */
1864 if ((type == SIR_MAC_MGMT_FRAME) &&
1865 (subType != SIR_MAC_MGMT_PROBE_REQ))
1866 {
1867 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1868 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1869 if (NULL == pAdapter)
1870 {
1871 /* Under assumtion that we don't receive any action frame
1872 * with BCST as destination we dropping action frame
1873 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001874 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1875 MAC_ADDRESS_STR ,
1876 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1877 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08001878 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001879 return;
1880 }
1881 }
1882
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001883
Jeff Johnson295189b2012-06-20 16:38:30 -07001884 if (NULL == pAdapter->dev)
1885 {
1886 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1887 return;
1888 }
1889
1890 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1891 {
1892 hddLog( LOGE, FL("pAdapter has invalid magic"));
1893 return;
1894 }
1895
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301896 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1897 if (NULL == pHddCtx)
1898 {
1899 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
1900 return;
1901 }
1902
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001903 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1904 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001905 {
1906 hdd_adapter_t *pMonAdapter =
1907 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1908
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001909 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001910 {
1911 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1912 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1913 pbFrames, frameType);
1914 return;
1915 }
1916 }
1917
1918 //Channel indicated may be wrong. TODO
1919 //Indicate an action frame.
1920 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1921 {
1922 freq = ieee80211_channel_to_frequency( rxChan,
1923 IEEE80211_BAND_2GHZ);
1924 }
1925 else
1926 {
1927 freq = ieee80211_channel_to_frequency( rxChan,
1928 IEEE80211_BAND_5GHZ);
1929 }
1930
Jeff Johnsone7245742012-09-05 17:12:55 -07001931 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301932 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301933
1934 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001935 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001936 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001937 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1938 {
1939 // public action frame
1940 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001941 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 -08001942 // P2P action frames
1943 {
1944 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08001945 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001946#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001947 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1948 {
1949 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1950 actionFrmType);
1951 }
1952 else
1953 {
1954 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1955 p2p_action_frame_type[actionFrmType]);
1956 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1957 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1958 {
1959 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1960 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001961 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001962 }
1963 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1964 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1965 {
1966 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001967 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1968 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001969 }
1970 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1971 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1972 {
1973 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1974 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1975 " completed state Autonomous GO formation");
1976 }
1977 }
1978#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301979 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
1980 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
1981 {
1982 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1983 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
1984 actionFrmType == WLAN_HDD_INVITATION_REQ ||
1985 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
1986 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
1987 {
1988 hddLog( LOG1, "Extend RoC timer on reception of"
1989 " Action Frame");
1990 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
1991 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
1992 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
1993 else
1994 extend_time = ACTION_FRAME_DEFAULT_WAIT;
1995 if (completion_done(&pAdapter->rem_on_chan_ready_event))
1996 {
1997 vos_timer_stop(
1998 &pRemainChanCtx->hdd_remain_on_chan_timer);
1999 status = vos_timer_start(
2000 &pRemainChanCtx->hdd_remain_on_chan_timer,
2001 extend_time);
2002 if (status != VOS_STATUS_SUCCESS)
2003 {
2004 hddLog( LOGE, "ROC timer start failed");
2005 }
2006 }
2007 else
2008 {
2009 // Buffer Packet
2010 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2011 {
2012 pRemainChanCtx->action_pkt_buff.frame_length =
2013 nFrameLength;
2014 pRemainChanCtx->action_pkt_buff.freq = freq;
2015 pRemainChanCtx->action_pkt_buff.frame_ptr
2016 = vos_mem_malloc(nFrameLength);
2017 vos_mem_copy(
2018 pRemainChanCtx->action_pkt_buff.frame_ptr,
2019 pbFrames, nFrameLength);
2020 hddLog( LOGE,"%s:"
2021 "Action Pkt Cached successfully !!!", __func__);
2022 }
2023 else
2024 {
2025 hddLog( LOGE,"%s:"
2026 "Frames are pending. dropping frame !!!",
2027 __func__);
2028 }
2029 return;
2030 }
2031 }
2032 }
2033 if (pRemainChanCtx != NULL &&
2034 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2035 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2036 hddLog( LOG1, "%s:"
2037 "Rcvd action frame after timer expired ", __func__);
2038
2039 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) ||
2040 (actionFrmType == WLAN_HDD_GO_NEG_REQ) ||
2041 (actionFrmType == WLAN_HDD_INVITATION_REQ) )
2042 {
2043 pScanInfo = &pHddCtx->scan_info;
2044 if((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2045 {
2046 hddLog(LOGE,"Action frame received when Scanning is in"
2047 " progress. Abort Scan.");
2048 hdd_abort_mac_scan(pAdapter->pHddCtx,
2049 pAdapter->sessionId,
2050 eCSR_SCAN_ABORT_DEFAULT);
2051 }
2052 }
2053 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2054 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2055 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2056 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2057 {
2058 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2059 __func__);
2060 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002061 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002062 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002063#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002064 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 -07002065 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002066 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
2067#ifdef WLAN_FEATURE_TDLS_DEBUG
2068 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2069 MAC_ADDR_ARRAY(mac),rxRssi);
2070#endif
2071 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2072 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002073 }
2074#endif
2075 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002076#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002077 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2078 {
2079 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2080 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2081 {
2082 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2083 actionFrmType);
2084 }
2085 else
2086 {
2087 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2088 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002089 }
2090 }
2091#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002092 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2093 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2094 {
2095 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal, hddWmmDscpToUpMapInfra);
2096 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002097 }
2098
Jeff Johnson295189b2012-06-20 16:38:30 -07002099 //Indicate Frame Over Normal Interface
2100 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2101
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002102#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2103 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2104 pbFrames, nFrameLength,
2105 GFP_ATOMIC );
2106#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002107 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2108 pbFrames, nFrameLength,
2109 GFP_ATOMIC );
2110#else
2111 cfg80211_rx_mgmt( pAdapter->dev, freq,
2112 pbFrames, nFrameLength,
2113 GFP_ATOMIC );
2114#endif //LINUX_VERSION_CODE
2115}
2116
2117/*
2118 * ieee80211_add_rx_radiotap_header - add radiotap header
2119 */
2120static int hdd_wlan_add_rx_radiotap_hdr (
2121 struct sk_buff *skb, int rtap_len, int flag )
2122{
2123 u8 rtap_temp[20] = {0};
2124 struct ieee80211_radiotap_header *rthdr;
2125 unsigned char *pos;
2126 u16 rx_flags = 0;
2127
2128 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2129
2130 /* radiotap header, set always present flags */
2131 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2132 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2133 rthdr->it_len = cpu_to_le16(rtap_len);
2134
2135 pos = (unsigned char *) (rthdr + 1);
2136
2137 /* the order of the following fields is important */
2138
2139 /* IEEE80211_RADIOTAP_FLAGS */
2140 *pos = 0;
2141 pos++;
2142
2143 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2144 /* ensure 2 byte alignment for the 2 byte field as required */
2145 if ((pos - (u8 *)rthdr) & 1)
2146 pos++;
2147 put_unaligned_le16(rx_flags, pos);
2148 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302149
Jeff Johnson295189b2012-06-20 16:38:30 -07002150 // actually push the data
2151 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2152
2153 return 0;
2154}
2155
2156static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2157 hdd_cfg80211_state_t* cfgState,
2158 tANI_BOOLEAN actionSendSuccess )
2159{
2160 struct ieee80211_radiotap_header *rthdr;
2161 unsigned char *pos;
2162 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002163#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002164#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2165 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2166#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002167#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002168
2169 /* 2 Byte for TX flags and 1 Byte for Retry count */
2170 u32 rtHdrLen = sizeof(*rthdr) + 3;
2171
2172 u8 *data;
2173
2174 /* We have to return skb with Data starting with MAC header. We have
2175 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2176 * entire skb->len from skb and then we will push cfgState->buf to skb
2177 * */
2178 if( NULL == skb_pull(skb, skb->len) )
2179 {
2180 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2181 kfree_skb(cfgState->skb);
2182 return;
2183 }
2184
2185 data = skb_push( skb, cfgState->len );
2186
2187 if (data == NULL)
2188 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002189 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002190 kfree_skb( cfgState->skb );
2191 return;
2192 }
2193
2194 memcpy( data, cfgState->buf, cfgState->len );
2195
2196 /* send frame to monitor interfaces now */
2197 if( skb_headroom(skb) < rtHdrLen )
2198 {
2199 hddLog( LOGE, FL("No headroom for rtap header"));
2200 kfree_skb(cfgState->skb);
2201 return;
2202 }
2203
2204 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2205
2206 memset( rthdr, 0, rtHdrLen );
2207 rthdr->it_len = cpu_to_le16( rtHdrLen );
2208 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2209 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2210 );
2211
2212 pos = (unsigned char *)( rthdr+1 );
2213
2214 // Fill TX flags
2215 *pos = actionSendSuccess;
2216 pos += 2;
2217
2218 // Fill retry count
2219 *pos = 0;
2220 pos++;
2221
2222 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002223 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002224 skb->pkt_type = PACKET_OTHERHOST;
2225 skb->protocol = htons(ETH_P_802_2);
2226 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002227#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002228#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002229 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002230#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002231#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002232 if (in_interrupt())
2233 netif_rx( skb );
2234 else
2235 netif_rx_ni( skb );
2236
2237 /* Enable Queues which we have disabled earlier */
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302238 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002239
2240}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302241