blob: dbce2b3ecd8b678332fb5bf5c1c53aab86945107 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**========================================================================
29
30 \file wlan_hdd_p2p.c
31
32 \brief WLAN Host Device Driver implementation for P2P commands interface
33
34 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
35
36 Qualcomm Confidential and Proprietary.
37
38 ========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070039
40#include <wlan_hdd_includes.h>
41#include <wlan_hdd_hostapd.h>
42#include <net/cfg80211.h>
43#include "sme_Api.h"
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -070044#include "sme_QosApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070045#include "wlan_hdd_p2p.h"
46#include "sapApi.h"
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053047#include "wlan_hdd_main.h"
Daram Sudha1f7e0e92013-12-17 07:52:31 +053048#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070049#include <linux/netdevice.h>
50#include <linux/skbuff.h>
51#include <linux/etherdevice.h>
52#include <net/ieee80211_radiotap.h>
Hoonki Lee1090c6a2013-01-16 17:40:54 -080053#ifdef FEATURE_WLAN_TDLS
54#include "wlan_hdd_tdls.h"
55#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053056#include "wlan_hdd_trace.h"
57#include "vos_types.h"
58#include "vos_trace.h"
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080059//Ms to Micro Sec
60#define MS_TO_MUS(x) ((x)*1000);
Daram Sudha1f7e0e92013-12-17 07:52:31 +053061tANI_U8* hdd_getActionString( tANI_U16 MsgType )
62{
63 switch (MsgType)
64 {
65 CASE_RETURN_STRING(SIR_MAC_ACTION_SPECTRUM_MGMT);
66 CASE_RETURN_STRING(SIR_MAC_ACTION_QOS_MGMT);
67 CASE_RETURN_STRING(SIR_MAC_ACTION_DLP);
68 CASE_RETURN_STRING(SIR_MAC_ACTION_BLKACK);
69 CASE_RETURN_STRING(SIR_MAC_ACTION_PUBLIC_USAGE);
70 CASE_RETURN_STRING(SIR_MAC_ACTION_RRM);
71 CASE_RETURN_STRING(SIR_MAC_ACTION_FAST_BSS_TRNST);
72 CASE_RETURN_STRING(SIR_MAC_ACTION_HT);
73 CASE_RETURN_STRING(SIR_MAC_ACTION_SA_QUERY);
74 CASE_RETURN_STRING(SIR_MAC_ACTION_PROT_DUAL_PUB);
75 CASE_RETURN_STRING(SIR_MAC_ACTION_WNM);
76 CASE_RETURN_STRING(SIR_MAC_ACTION_UNPROT_WNM);
77 CASE_RETURN_STRING(SIR_MAC_ACTION_TDLS);
78 CASE_RETURN_STRING(SIR_MAC_ACITON_MESH);
79 CASE_RETURN_STRING(SIR_MAC_ACTION_MULTIHOP);
80 CASE_RETURN_STRING(SIR_MAC_SELF_PROTECTED);
81 CASE_RETURN_STRING(SIR_MAC_ACTION_WME);
82 CASE_RETURN_STRING(SIR_MAC_ACTION_VHT);
83 default:
84 return ("UNKNOWN");
85 }
86}
87
88
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070089#ifdef WLAN_FEATURE_P2P_DEBUG
90#define MAX_P2P_ACTION_FRAME_TYPE 9
91const char *p2p_action_frame_type[]={"GO Negotiation Request",
92 "GO Negotiation Response",
93 "GO Negotiation Confirmation",
94 "P2P Invitation Request",
95 "P2P Invitation Response",
96 "Device Discoverability Request",
97 "Device Discoverability Response",
98 "Provision Discovery Request",
99 "Provision Discovery Response"};
100
101/* We no need to protect this variable since
102 * there is no chance of race to condition
103 * and also not make any complicating the code
104 * just for debugging log
105 */
106tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
107
108#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800109#ifdef WLAN_FEATURE_TDLS_DEBUG
110#define MAX_TDLS_ACTION_FRAME_TYPE 11
111const char *tdls_action_frame_type[] = {"TDLS Setup Request",
112 "TDLS Setup Response",
113 "TDLS Setup Confirm",
114 "TDLS Teardown",
115 "TDLS Peer Traffic Indication",
116 "TDLS Channel Switch Request",
117 "TDLS Channel Switch Response",
118 "TDLS Peer PSM Request",
119 "TDLS Peer PSM Response",
120 "TDLS Peer Traffic Response",
121 "TDLS Discovery Request" };
122#endif
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700123
Jeff Johnson295189b2012-06-20 16:38:30 -0700124extern struct net_device_ops net_ops_struct;
125
126static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
127 int rtap_len, int flag );
128
129static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
130 hdd_cfg80211_state_t* cfgState,
131 tANI_BOOLEAN actionSendSuccess );
132
133static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Rashmi Ramannac7744532013-10-06 16:49:08 +0530134 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -0700135 tANI_U8* pbFrames,
136 tANI_U8 frameType );
vamsi9bd92b72013-12-26 14:11:29 +0530137
138static v_BOOL_t hdd_p2p_is_action_type_rsp( const u8 *buf )
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530139{
vamsi9bd92b72013-12-26 14:11:29 +0530140 tActionFrmType actionFrmType;
141 const u8 *ouiPtr;
142
143 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
144 WLAN_HDD_PUBLIC_ACTION_FRAME ) {
145 return VOS_FALSE;
146 }
147
148 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] !=
149 WLAN_HDD_VENDOR_SPECIFIC_ACTION ) {
150 return VOS_FALSE;
151 }
152
153 ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET];
154
155 if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) {
156 return VOS_FALSE;
157 }
158
159 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] !=
160 WLAN_HDD_WFA_P2P_OUI_TYPE ) {
161 return VOS_FALSE;
162 }
163
Ahmad Kholaife5ec2cd2014-03-19 13:22:04 +0530164 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
vamsi9bd92b72013-12-26 14:11:29 +0530165 if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
166 actionFrmType != WLAN_HDD_GO_NEG_REQ &&
167 actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
168 actionFrmType != WLAN_HDD_PROV_DIS_REQ )
169 return VOS_TRUE;
170 else
171 return VOS_FALSE;
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530172}
Jeff Johnson295189b2012-06-20 16:38:30 -0700173
Jeff Johnson295189b2012-06-20 16:38:30 -0700174eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
175 eHalStatus status )
176{
177 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700178 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
179 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
180
181 if( pRemainChanCtx == NULL )
182 {
183 hddLog( LOGW,
184 "%s: No Rem on channel pending for which Rsp is received", __func__);
185 return eHAL_STATUS_SUCCESS;
186 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530187 hddLog( VOS_TRACE_LEVEL_INFO,
188 "Received ROC rsp (request type %d, channel %d, cookie %llu",
189 pRemainChanCtx->rem_on_chan_request,
190 pRemainChanCtx->chan.center_freq,
191 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700192 cfgState->remain_on_chan_ctx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530193 vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
194 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
195 if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
Jeff Johnson295189b2012-06-20 16:38:30 -0700196 {
197 if( cfgState->buf )
198 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530199 hddLog( LOGP,
Jeff Johnson295189b2012-06-20 16:38:30 -0700200 "%s: We need to receive yet an ack from one of tx packet",
201 __func__);
202 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800203 cfg80211_remain_on_channel_expired(
204#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
205 pRemainChanCtx->dev->ieee80211_ptr,
206#else
207 pRemainChanCtx->dev,
208#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700209 pRemainChanCtx->cookie,
210 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700211#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
212 pRemainChanCtx->chan_type,
213#endif
214 GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -0700215 }
216
Jeff Johnson295189b2012-06-20 16:38:30 -0700217
218 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700219 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
220 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700221 )
222 {
223 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800224 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
225 {
226 sme_DeregisterMgmtFrame(
227 hHal, sessionId,
228 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
229 NULL, 0 );
230 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700231 }
232 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
233 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
234 )
235 {
236 WLANSAP_DeRegisterMgmtFrame(
237 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
238 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
239 NULL, 0 );
240 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530241 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
242 && pRemainChanCtx->action_pkt_buff.frame_length != 0)
243 {
244 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
245 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800246 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800247 pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700248 complete(&pAdapter->cancel_rem_on_chan_var);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530249 pAdapter->is_roc_inprogress = FALSE;
250 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 return eHAL_STATUS_SUCCESS;
252}
253
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530254VOS_STATUS wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700255{
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530257 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700258 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700259
Jeff Johnson32d95a32012-09-10 13:15:23 -0700260 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700261 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530262 hddLog(VOS_TRACE_LEVEL_INFO,
263 "Cancel Existing ROC (cookie=%llu)",
264 cfgState->remain_on_chan_ctx->cookie);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700265
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530266 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
267 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress == TRUE)
268 {
269 hddLog( LOG1,
270 "ROC timer cancellation in progress,"
271 " wait for completion");
272 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
273 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
274 if (0 >= status)
275 {
276 hddLog( LOGE,
277 "%s:wait on cancel_rem_on_chan_var failed %d",
278 __func__, status);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530279 return VOS_STATUS_E_FAILURE;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530280 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530281 return VOS_STATUS_SUCCESS;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530282 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530283
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530284 /* Wait till remain on channel ready indication before issuing cancel
285 * remain on channel request, otherwise if remain on channel not
286 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 * will be in unknown state.
288 */
289 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
290 msecs_to_jiffies(WAIT_REM_CHAN_READY));
c_hpothu7f63e882013-10-02 19:13:35 +0530291 if (0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 {
293 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530294 "%s: timeout waiting for remain on channel ready indication %d",
295 __func__, status);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530296 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
297 return VOS_STATUS_E_FAILURE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700298 }
299
300 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530301 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530302
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 /* Issue abort remain on chan request to sme.
304 * The remain on channel callback will make sure the remain_on_chan
305 * expired event is sent.
306 */
307 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700308 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
309 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 )
311 {
312 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
313 pAdapter->sessionId );
314 }
315 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
316 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
317 )
318 {
319 WLANSAP_CancelRemainOnChannel(
320 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
321 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700322
Jeff Johnson32d95a32012-09-10 13:15:23 -0700323 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700324 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Jeff Johnson32d95a32012-09-10 13:15:23 -0700325
c_hpothu7f63e882013-10-02 19:13:35 +0530326 if (0 >= status)
Jeff Johnson32d95a32012-09-10 13:15:23 -0700327 {
328 hddLog( LOGE,
c_hpothu7f63e882013-10-02 19:13:35 +0530329 "%s: timeout waiting for cancel remain on channel ready indication %d",
330 __func__, status);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700331 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530332 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700333 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530334 return VOS_STATUS_SUCCESS;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700335}
336
337int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
338{
339 int status = 0;
340 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
341
342 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
343 {
344 //Cancel Existing Remain On Channel
345 //If no action frame is pending
346 if( cfgState->remain_on_chan_ctx != NULL)
347 {
348 //Check whether Action Frame is pending or not
349 if( cfgState->buf == NULL)
350 {
351 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
352 }
353 else
354 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530355 hddLog(VOS_TRACE_LEVEL_DEBUG,
356 "Cannot Cancel Existing Remain on Channel");
Jeff Johnson32d95a32012-09-10 13:15:23 -0700357 status = -EBUSY;
358 }
359 }
360 }
361 return status;
362}
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530363void wlan_hdd_remain_on_chan_timeout(void *data)
364{
365 hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
366 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
367 hdd_cfg80211_state_t *cfgState;
368 if ( NULL == pAdapter )
369 {
370 hddLog( LOGE, FL("pAdapter is NULL !!!"));
371 return;
372 }
373 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
374 pRemainChanCtx = cfgState->remain_on_chan_ctx;
375 if (NULL == pRemainChanCtx)
376 {
377 hddLog( LOGE, FL("No Remain on channel is pending"));
378 return;
379 }
380 if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
381 {
382 hddLog( LOGE, FL("Cancellation already in progress"));
383 return;
384 }
385
386 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
387 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
388 hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
389 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
390 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
391 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
392 )
393 {
394 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
395 pAdapter->sessionId );
396 }
397 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
398 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
399 )
400 {
401 WLANSAP_CancelRemainOnChannel(
402 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
403 }
404 hdd_allow_suspend();
405}
Jeff Johnson32d95a32012-09-10 13:15:23 -0700406
407static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
408 struct net_device *dev,
409 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700410#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700411 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700412#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700413 unsigned int duration, u64 *cookie,
414 rem_on_channel_request_type_t request_type )
415{
416 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
417 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
418 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530419 VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
420 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
421 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
422 hdd_adapter_t *pAdapter_temp;
423 VOS_STATUS status;
424 v_BOOL_t isGoPresent = VOS_FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530425 VOS_STATUS checkReadyInd;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700426 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
427 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700428#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530429 hddLog(VOS_TRACE_LEVEL_INFO,
430 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
431 " request type %d, cookie %llu",
432 chan->hw_value, chan->center_freq, channel_type, duration,
433 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700434#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530435 hddLog(VOS_TRACE_LEVEL_INFO,
436 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
437 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
438 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700439#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700440 //Cancel existing remain On Channel if any
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530441 checkReadyInd = wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
442 if (VOS_STATUS_SUCCESS != checkReadyInd)
443 {
444 hddLog( LOGE, FL("Cancel Roc in progress"));
445 return -EBUSY;
446 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700447
Jeff Johnsone7245742012-09-05 17:12:55 -0700448 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700449 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700450 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700451 * channel requets when Load/Unload is in progress*/
Rashmi Ramannab1429032014-04-26 14:59:09 +0530452 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(((hdd_context_t *)pAdapter->pHddCtx))
453 || hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx))
Jeff Johnson295189b2012-06-20 16:38:30 -0700454 {
455 hddLog( LOGE,
Rashmi Ramannab1429032014-04-26 14:59:09 +0530456 "%s: Wlan Load/Unload or Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700457 return -EBUSY;
458 }
459
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700460 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
461 {
462 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
463 "%s:LOGP in Progress. Ignore!!!", __func__);
464 return -EAGAIN;
465 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700466 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
467 if( NULL == pRemainChanCtx )
468 {
469 hddLog(VOS_TRACE_LEVEL_FATAL,
470 "%s: Not able to allocate memory for Channel context",
471 __func__);
472 return -ENOMEM;
473 }
474
475 vos_mem_copy( &pRemainChanCtx->chan, chan,
476 sizeof(struct ieee80211_channel) );
477
Yue Maf49ba872013-08-19 12:04:25 -0700478#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700479 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700480#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700481 pRemainChanCtx->duration = duration;
482 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800483 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700484 pRemainChanCtx->cookie = *cookie;
485 pRemainChanCtx->rem_on_chan_request = request_type;
486 cfgState->remain_on_chan_ctx = pRemainChanCtx;
487 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530488 pRemainChanCtx->action_pkt_buff.freq = 0;
489 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
490 pRemainChanCtx->action_pkt_buff.frame_length = 0;
491 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530492 pRemainChanCtx->is_pending_roc_cancelled = FALSE;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530493 /* Initialize Remain on chan timer */
494 vos_status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
495 VOS_TIMER_TYPE_SW,
496 wlan_hdd_remain_on_chan_timeout,
497 pAdapter);
498 if (vos_status != VOS_STATUS_SUCCESS)
499 {
500 hddLog(VOS_TRACE_LEVEL_ERROR,
501 "%s: Not able to initalize remain_on_chan timer", __func__);
502 }
503 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
504 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
505 {
506 pAdapter_temp = pAdapterNode->pAdapter;
507 if (WLAN_HDD_P2P_GO == pAdapter_temp->device_mode)
508 {
509 isGoPresent = VOS_TRUE;
510 }
511 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
512 pAdapterNode = pNext;
513 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530514 hdd_prevent_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700515 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
516
517 //call sme API to start remain on channel.
518 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700519 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
520 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700521 )
522 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700523 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700524 //call sme API to start remain on channel.
525 sme_RemainOnChannel(
Rashmi Ramannac7744532013-10-06 16:49:08 +0530526 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
527 chan->hw_value, duration,
528 wlan_hdd_remain_on_channel_callback, pAdapter,
529 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE);
Jeff Johnson295189b2012-06-20 16:38:30 -0700530
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800531 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
532 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530533 if( eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame(
534 WLAN_HDD_GET_HAL_CTX(pAdapter),
535 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
536 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ))
537 {
538 hddLog(VOS_TRACE_LEVEL_ERROR,
539 "sme_RegisterMgmtFrame returned fail");
540 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800541 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700542
543 }
544 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
545 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
546 )
547 {
548 //call sme API to start remain on channel.
Jeff Johnson43971f52012-07-17 12:26:56 -0700549 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
Jeff Johnson295189b2012-06-20 16:38:30 -0700550 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
551 chan->hw_value, duration,
552 wlan_hdd_remain_on_channel_callback, pAdapter ))
553
554 {
555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
556 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
557 cfgState->remain_on_chan_ctx = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -0700558 vos_mem_free (pRemainChanCtx);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530559 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700560 return -EINVAL;
561 }
562
563
Jeff Johnson43971f52012-07-17 12:26:56 -0700564 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
Jeff Johnson295189b2012-06-20 16:38:30 -0700565 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
566 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
567 NULL, 0 ))
568 {
569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
570 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
571 WLANSAP_CancelRemainOnChannel(
572 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530573 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700574 return -EINVAL;
575 }
576
577 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530578
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530579 pAdapter->is_roc_inprogress = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700580 return 0;
581
582}
583
584int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800585#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
586 struct wireless_dev *wdev,
587#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700588 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800589#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700590 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700591#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700592 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700593#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700594 unsigned int duration, u64 *cookie )
595{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800596#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
597 struct net_device *dev = wdev->netdev;
598#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530599 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
600
601 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
602 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
603 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Jeff Johnson295189b2012-06-20 16:38:30 -0700604 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700605 chan,
606#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
607 channel_type,
608#endif
609 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700610 REMAIN_ON_CHANNEL_REQUEST);
611}
612
613void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
614{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530615 hdd_cfg80211_state_t *cfgState = NULL;
616 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530617 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530618 if (NULL == pAdapter)
619 {
620 hddLog(LOGE, FL("pAdapter is NULL"));
621 return;
622 }
623 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
624 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530625 hddLog( LOG1, "Ready on chan ind");
Jeff Johnson295189b2012-06-20 16:38:30 -0700626 if( pRemainChanCtx != NULL )
627 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530628 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
629 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
630 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530631 //start timer for actual duration
632 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
633 (pRemainChanCtx->duration));
634 if (VOS_STATUS_SUCCESS!=status)
635 {
636 hddLog( LOGE, FL("Remain on Channel timer start failed"));
637 }
638 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700639 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800640 cfg80211_ready_on_channel(
641#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
642 pAdapter->dev->ieee80211_ptr,
643#else
644 pAdapter->dev,
645#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800646 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700647 &pRemainChanCtx->chan,
648#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
649 pRemainChanCtx->chan_type,
650#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700651 pRemainChanCtx->duration, GFP_KERNEL );
652 }
653#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530654 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700655 {
656 complete(&pAdapter->offchannel_tx_event);
657 }
658#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530659 // Check for cached action frame
660 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
661 {
662#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
663 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
664 pRemainChanCtx->action_pkt_buff.freq, 0,
665 pRemainChanCtx->action_pkt_buff.frame_ptr,
666 pRemainChanCtx->action_pkt_buff.frame_length,
667 GFP_ATOMIC );
668#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
669 cfg80211_rx_mgmt( pAdapter->dev,
670 pRemainChanCtx->action_pkt_buff.freq, 0,
671 pRemainChanCtx->action_pkt_buff.frame_ptr,
672 pRemainChanCtx->action_pkt_buff.frame_length,
673 GFP_ATOMIC );
674#else
675 cfg80211_rx_mgmt( pAdapter->dev,
676 pRemainChanCtx->action_pkt_buff.freq,
677 pRemainChanCtx->action_pkt_buff.frame_ptr,
678 pRemainChanCtx->action_pkt_buff.frame_length,
679 GFP_ATOMIC );
680#endif //LINUX_VERSION_CODE
681 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
682 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
683 pRemainChanCtx->action_pkt_buff.frame_length = 0;
684 pRemainChanCtx->action_pkt_buff.freq = 0;
685 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
686 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530687 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
688 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700689 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530690 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
691 {
692 /* since pRemainChanCtx->is_pending_roc_cancelled is
693 * set, it means Cancel Reamain on channel command is
694 * pending because remain on channel event was not
695 * ready when cancel ROC was issued.So issue
696 * cancel ROC now.
697 */
698 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
699 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700700 }
701 else
702 {
703 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
704 }
705 return;
706}
707
708int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800709#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
710 struct wireless_dev *wdev,
711#else
712 struct net_device *dev,
713#endif
714 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700715{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800716#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
717 struct net_device *dev = wdev->netdev;
718#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700719 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700720 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530721 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530722 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
723 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530724 u64 cookie_dummy;
725 cookie_dummy = cookie << 32;
726 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
727 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
728 pAdapter->sessionId, cookie_dummy));
729 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -0700730
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530731 status = wlan_hdd_validate_context(pHddCtx);
732
733 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700734 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530735 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
736 "%s: HDD context is not valid", __func__);
737 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700738 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530739 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
740
Jeff Johnson295189b2012-06-20 16:38:30 -0700741 /* FIXME cancel currently running remain on chan.
742 * Need to check cookie and cancel accordingly
743 */
744 if( (cfgState->remain_on_chan_ctx == NULL) ||
745 (cfgState->remain_on_chan_ctx->cookie != cookie) )
746 {
747 hddLog( LOGE,
748 "%s: No Remain on channel pending with specified cookie value",
749 __func__);
750 return -EINVAL;
751 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530752 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
753 {
754 /* wait until remain on channel ready event received
755 * for already issued remain on channel request */
756 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
757 msecs_to_jiffies(WAIT_REM_CHAN_READY));
758 if (0 >= status)
759 {
760 hddLog( LOGE,
761 "%s: timeout waiting for remain on channel ready indication %d",
762 __func__, status);
763 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
764 return 0;
765
766 }
767 }
768 else
769 {
770 hddLog( LOG1, FL("Cancel ROC event is already pending, "
771 "waiting for ready on channel indication.") );
772 return 0;
773 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530774 if (NULL != cfgState->remain_on_chan_ctx)
775 {
776 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
777 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
778 {
779 hddLog( LOG1,
780 FL("ROC timer cancellation in progress,"
781 " wait for completion"));
782 status = wait_for_completion_interruptible_timeout(
783 &pAdapter->cancel_rem_on_chan_var,
784 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
785 if (0 >= status)
786 {
787 hddLog( LOGE,
788 "%s:wait on cancel_rem_on_chan_var failed %d",
789 __func__, status);
790 }
791 return 0;
792 }
793 else
794 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
795 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700796 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
797 /* Issue abort remain on chan request to sme.
798 * The remain on channel callback will make sure the remain_on_chan
799 * expired event is sent.
800 */
801 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700802 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
803 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700804 )
805 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530806 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700807 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
808 sessionId );
809 }
810 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
811 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
812 )
813 {
814 WLANSAP_CancelRemainOnChannel(
815 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
816 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530817 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700818 {
819 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
820 __func__, pAdapter->device_mode);
821 return -EIO;
822 }
c_hpothu7f63e882013-10-02 19:13:35 +0530823 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700824 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +0530825 if (0 >= status)
826 {
827 hddLog( LOGE,
828 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
829 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530830 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700831 return 0;
832}
833
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800834#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530835int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800836 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700837#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800838 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700839 bool channel_type_valid,
840#endif
841 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800842 const u8 *buf, size_t len, bool no_cck,
843 bool dont_wait_for_ack, u64 *cookie )
844#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530845int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700846 struct ieee80211_channel *chan, bool offchan,
847 enum nl80211_channel_type channel_type,
848 bool channel_type_valid, unsigned int wait,
849 const u8 *buf, size_t len, bool no_cck,
850 bool dont_wait_for_ack, u64 *cookie )
851#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
DARAM SUDHA39eede62014-02-12 11:16:40 +0530852int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700853 struct ieee80211_channel *chan, bool offchan,
854 enum nl80211_channel_type channel_type,
855 bool channel_type_valid, unsigned int wait,
856 const u8 *buf, size_t len, u64 *cookie )
857#else
DARAM SUDHA39eede62014-02-12 11:16:40 +0530858int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700859 struct ieee80211_channel *chan,
860 enum nl80211_channel_type channel_type,
861 bool channel_type_valid,
862 const u8 *buf, size_t len, u64 *cookie )
863#endif //LINUX_VERSION_CODE
864{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800865#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
866 struct net_device *dev = wdev->netdev;
867#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700868 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
869 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530870 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530871 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -0700872 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
873 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
874 tActionFrmType actionFrmType;
875 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530876 int status;
Chet Lanctot186b5732013-03-18 10:26:30 -0700877#ifdef WLAN_FEATURE_11W
878 tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit
879#endif
Jeff Johnsone7245742012-09-05 17:12:55 -0700880
Jeff Johnson295189b2012-06-20 16:38:30 -0700881#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
882 hdd_adapter_t *goAdapter;
883#endif
884
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530885 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
886 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
887 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530888 status = wlan_hdd_validate_context(pHddCtx);
889
890 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800891 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
893 "%s: HDD context is not valid", __func__);
894 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800895 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530896
c_hpothu7f63e882013-10-02 19:13:35 +0530897 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
898 __func__, pAdapter->device_mode, type);
899
900
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700901#ifdef WLAN_FEATURE_P2P_DEBUG
902 if ((type == SIR_MAC_MGMT_FRAME) &&
903 (subType == SIR_MAC_MGMT_ACTION) &&
904 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
905 {
906 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800907 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700908 {
909 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
910 actionFrmType);
911 }
912 else
913 {
914 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
915 p2p_action_frame_type[actionFrmType]);
916 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
917 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
918 {
919 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
920 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -0800921 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700922 }
923 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
924 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
925 {
926 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
927 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
928 " completed state");
929 }
930 }
931 }
932#endif
933
Jeff Johnsone7245742012-09-05 17:12:55 -0700934#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
935 noack = dont_wait_for_ack;
936#endif
937
938 //If the wait is coming as 0 with off channel set
939 //then set the wait to 200 ms
940 if (offchan && !wait)
941 wait = ACTION_FRAME_DEFAULT_WAIT;
942
Jeff Johnson295189b2012-06-20 16:38:30 -0700943 //Call sme API to send out a action frame.
944 // OR can we send it directly through data path??
945 // After tx completion send tx status back.
946 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
947 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
948 )
949 {
Jeff Johnson295189b2012-06-20 16:38:30 -0700950 if (type == SIR_MAC_MGMT_FRAME)
951 {
952 if (subType == SIR_MAC_MGMT_PROBE_RSP)
953 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530954 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -0700955 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530956 */
Jeff Johnson295189b2012-06-20 16:38:30 -0700957 goto err_rem_channel;
958 }
959 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
960 (subType == SIR_MAC_MGMT_DEAUTH))
961 {
Jeff Johnsone7245742012-09-05 17:12:55 -0700962 /* During EAP failure or P2P Group Remove supplicant
963 * is sending del_station command to driver. From
964 * del_station function, Driver will send deauth frame to
965 * p2p client. No need to send disassoc frame from here.
966 * so Drop the frame here and send tx indication back to
967 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -0700968 */
969 tANI_U8 dstMac[ETH_ALEN] = {0};
970 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -0700971 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -0700972 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -0800973 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -0700974 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -0800975 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -0700976 goto err_rem_channel;
977 }
978 }
979 }
980
981 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -0800982 {
983 if ( !noack )
984 {
985 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
986 __func__);
987 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
988 }
989 else
990 {
991 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
992 __func__);
993 return -EBUSY;
994 }
995 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700996
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530997 if( subType == SIR_MAC_MGMT_ACTION)
998 {
999 hddLog( LOG1, "Action frame tx request : %s",
1000 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1001 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001002
1003#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1004 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1005
1006 //If GO adapter exists and operating on same frequency
1007 //then we will not request remain on channel
1008 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1009 == goAdapter->sessionCtx.ap.operatingChannel ) )
1010 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301011 /* if GO exist and is not off channel
1012 * wait time should be zero.
1013 */
1014 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001015 goto send_frame;
1016 }
1017#endif
1018
1019#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1020 if( offchan && wait)
1021 {
1022 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301023 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001024 // In case of P2P Client mode if we are already
1025 // on the same channel then send the frame directly
1026
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301027 if( (cfgState->remain_on_chan_ctx != NULL) &&
1028 (cfgState->current_freq == chan->center_freq)
1029 )
1030 {
1031 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1032 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301033 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301034 /* Some times FW is taking almost 500 msec for
1035 * full 15 retries, which leads to ROC expiration
1036 * by the time peer gets response from other peer.
1037 * Therefore as part of temporary fix , in host
1038 * ROC time is extended. For frames where we are
1039 * expecting response from peer , its extended by
1040 * 500 msec to make ROC wait time as 1 sec and
1041 * in other cases its extended by 300 msec to make
1042 * total ROC wait as 500 msec.
1043 * TODO: FW needs to fix as why 15 retry is taking
1044 * such long time.
1045 */
1046 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1047 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1048 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1049 wait = wait + ACTION_FRAME_RSP_WAIT;
1050 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1051 actionFrmType == WLAN_HDD_INVITATION_RESP )
1052 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301053 vos_timer_stop(
1054 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1055 status = vos_timer_start(
1056 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1057 wait);
1058 if ( status != VOS_STATUS_SUCCESS )
vamsida0e5ab2013-12-26 14:33:27 +05301059 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301060 hddLog( LOGE, "Remain on Channel timer start failed");
1061 }
1062
1063 hddLog(VOS_TRACE_LEVEL_INFO,
1064 "action frame: extending the wait time %u",
1065 wait);
1066 goto send_frame;
1067 }
1068 else
1069 {
1070 if ( TRUE ==
1071 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1072 {
1073 hddLog(VOS_TRACE_LEVEL_INFO,
1074 "action frame tx: waiting for completion of ROC ");
1075
1076 status = wait_for_completion_interruptible_timeout(
1077 &pAdapter->cancel_rem_on_chan_var,
1078 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1079 if (0 >= status)
1080 {
1081 hddLog( LOGE,
1082 "%s:wait on cancel_rem_on_chan_var failed %d",
1083 __func__, status);
1084 }
vamsida0e5ab2013-12-26 14:33:27 +05301085 }
1086 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301087 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301088 hddLog(VOS_TRACE_LEVEL_INFO,
1089 "action frame: Request ROC for wait time %u", wait);
1090
Jeff Johnson295189b2012-06-20 16:38:30 -07001091 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001092 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001093 chan,
1094#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1095 channel_type,
1096#endif
1097 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301098 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001099
1100 if(0 != status)
1101 {
1102 if( (-EBUSY == status) &&
1103 (cfgState->current_freq == chan->center_freq) )
1104 {
1105 goto send_frame;
1106 }
1107 goto err_rem_channel;
1108 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001109 /* Wait for driver to be ready on the requested channel */
1110 status = wait_for_completion_interruptible_timeout(
1111 &pAdapter->offchannel_tx_event,
1112 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301113 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001114 {
c_hpothu7f63e882013-10-02 19:13:35 +05301115 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001116 goto err_rem_channel;
1117 }
1118 }
1119 else if ( offchan )
1120 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001121 /* Check before sending action frame
1122 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001123 if(NULL == cfgState->remain_on_chan_ctx)
1124 {
1125 goto err_rem_channel;
1126 }
1127 }
1128 send_frame:
1129#endif
1130
Jeff Johnsone7245742012-09-05 17:12:55 -07001131 if(!noack)
1132 {
1133 cfgState->buf = vos_mem_malloc( len ); //buf;
1134 if( cfgState->buf == NULL )
1135 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001136
Jeff Johnsone7245742012-09-05 17:12:55 -07001137 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001138
Jeff Johnsone7245742012-09-05 17:12:55 -07001139 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001140
1141#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001142 if( cfgState->remain_on_chan_ctx )
1143 {
1144 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1145 *cookie = cfgState->action_cookie;
1146 }
1147 else
1148 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001149#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001150 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001151 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001152#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001153 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001154#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301155 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001156
1157 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001158 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1159 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001160 )
1161 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001162 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001163
Jeff Johnsone7245742012-09-05 17:12:55 -07001164 if ((type == SIR_MAC_MGMT_FRAME) &&
1165 (subType == SIR_MAC_MGMT_ACTION) &&
1166 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001167 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001168 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301169 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001170 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001171 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001172 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301173 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001174 }
1175 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1176 {
1177 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301178 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001179 }
1180 }
Chet Lanctot186b5732013-03-18 10:26:30 -07001181#ifdef WLAN_FEATURE_11W
1182 if ((type == SIR_MAC_MGMT_FRAME) &&
1183 (subType == SIR_MAC_MGMT_ACTION) &&
1184 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME))
1185 {
1186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1187 "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query");
1188 // Since this is an SA Query Action Frame, we have to protect it
1189 WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]);
1190 }
1191#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001192 if (eHAL_STATUS_SUCCESS !=
1193 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301194 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001195 {
1196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1197 "%s: sme_sendAction returned fail", __func__);
1198 goto err;
1199 }
1200 }
1201 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1202 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1203 )
1204 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001205 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001206 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001207 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001208 {
1209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1210 "%s: WLANSAP_SendAction returned fail", __func__);
1211 goto err;
1212 }
1213 }
1214
1215 return 0;
1216err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001217 if(!noack)
1218 {
1219 hdd_sendActionCnf( pAdapter, FALSE );
1220 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001221 return 0;
1222err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001223 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001224 cfg80211_mgmt_tx_status(
1225#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1226 pAdapter->dev->ieee80211_ptr,
1227#else
1228 pAdapter->dev,
1229#endif
1230 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001231 return 0;
1232}
1233
1234#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001235#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1236int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1237 struct wireless_dev *wdev,
1238 u64 cookie)
1239{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301240 u64 cookie_dummy;
1241 cookie_dummy = cookie << 32;
1242 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1243 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001244 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1245}
1246#else
1247int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001248 struct net_device *dev,
1249 u64 cookie)
1250{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301251 u64 cookie_dummy;
1252 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1253 cookie_dummy = cookie << 32;
1254 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1255 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1256 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001257 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1258}
1259#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001260#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001261
1262void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1263{
1264 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1265
Jeff Johnsone7245742012-09-05 17:12:55 -07001266 cfgState->actionFrmState = HDD_IDLE;
1267
Jeff Johnson295189b2012-06-20 16:38:30 -07001268 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1269 if( NULL == cfgState->buf )
1270 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001271 return;
1272 }
1273
1274 /* If skb is NULL it means this packet was received on CFG80211 interface
1275 * else it was received on Monitor interface */
1276 if( cfgState->skb == NULL )
1277 {
1278 /*
1279 * buf is the same pointer it passed us to send. Since we are sending
1280 * it through control path, we use different buffers.
1281 * In case of mac80211, they just push it to the skb and pass the same
1282 * data while sending tx ack status.
1283 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001284 cfg80211_mgmt_tx_status(
1285#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1286 pAdapter->dev->ieee80211_ptr,
1287#else
1288 pAdapter->dev,
1289#endif
1290 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001291 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1292 vos_mem_free( cfgState->buf );
1293 cfgState->buf = NULL;
1294 }
1295 else
1296 {
1297 hdd_adapter_t* pMonAdapter =
1298 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1299 if( pMonAdapter == NULL )
1300 {
1301 hddLog( LOGE, "Not able to get Monitor Adapter");
1302 cfgState->skb = NULL;
1303 vos_mem_free( cfgState->buf );
1304 cfgState->buf = NULL;
1305 complete(&pAdapter->tx_action_cnf_event);
1306 return;
1307 }
1308 /* Send TX completion feedback over monitor interface. */
1309 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1310 cfgState->skb = NULL;
1311 vos_mem_free( cfgState->buf );
1312 cfgState->buf = NULL;
1313 /* Look for the next Mgmt packet to TX */
1314 hdd_mon_tx_mgmt_pkt(pAdapter);
1315 }
1316 complete(&pAdapter->tx_action_cnf_event);
1317}
1318
1319/**
1320 * hdd_setP2pNoa
1321 *
1322 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301323 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001324 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1325 *
1326 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301327 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001328 *
1329 *ASSUMPTIONS:
1330 *
1331 *
1332 *NOTE:
1333 *
1334 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301335 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001336 *
1337 * @return Status
1338 */
1339
1340int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1341{
1342 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1343 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1344 VOS_STATUS status = VOS_STATUS_SUCCESS;
1345 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001346 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001347 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001348 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001349
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001350 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001351 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301352 {
1353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1354 "%s: strnchr failed to find delimeter",__func__);
1355 return -EINVAL;
1356 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001357 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001358 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1359 if (ret < 3)
1360 {
1361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1362 "%s: P2P_SET GO NoA: fail to read param "
1363 "count=%d duration=%d interval=%d \n",
1364 __func__, count, start_time, duration);
1365 return -EINVAL;
1366 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001367 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001368 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001369 __func__, count, start_time, duration);
1370 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001371 /* PS Selection
1372 * Periodic NoA (2)
1373 * Single NOA (4)
1374 */
1375 NoA.opp_ps = 0;
1376 NoA.ctWindow = 0;
1377 if (count == 1)
1378 {
1379 NoA.duration = 0;
1380 NoA.single_noa_duration = duration;
1381 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1382 }
1383 else
1384 {
1385 NoA.duration = duration;
1386 NoA.single_noa_duration = 0;
1387 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1388 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001389 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001390 NoA.count = count;
1391 NoA.sessionid = pAdapter->sessionId;
1392
1393 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1394 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1395 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001396 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001397 NoA.ctWindow, NoA.duration, NoA.interval,
1398 NoA.count, NoA.single_noa_duration,
1399 NoA.psSelection);
1400
1401 sme_p2pSetPs(hHal, &NoA);
1402 return status;
1403}
1404
1405/**
1406 * hdd_setP2pOpps
1407 *
1408 *FUNCTION:
1409 * This function is called from hdd_hostapd_ioctl function when Driver
1410 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1411 *
1412 *LOGIC:
1413 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1414 *
1415 *ASSUMPTIONS:
1416 *
1417 *
1418 *NOTE:
1419 *
1420 * @param dev Pointer to net device structure
1421 * @param command Pointer to command
1422 *
1423 * @return Status
1424 */
1425
1426int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1427{
1428 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1429 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1430 VOS_STATUS status = VOS_STATUS_SUCCESS;
1431 tP2pPsConfig NoA;
1432 char *param;
1433 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001434 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001435
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001436 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001437 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301438 {
1439 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1440 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001441 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301442 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001443 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001444 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1445 if (ret < 3)
1446 {
1447 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1448 "%s: P2P_SET GO PS: fail to read param "
1449 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1450 __func__, legacy_ps, opp_ps, ctwindow);
1451 return -EINVAL;
1452 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001453 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001454 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001455 __func__, legacy_ps, opp_ps, ctwindow);
1456
1457 /* PS Selection
1458 * Opportunistic Power Save (1)
1459 */
1460
1461 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1462 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301463 * values are coming from wpa_supplicant as -1.
1464 * Example : User want to set ctWindow with 30 then wpa_cli command :
1465 * P2P_SET ctwindow 30
1466 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001467 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301468 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001469 if (ctwindow != -1)
1470 {
1471
1472 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001473 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001474 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1475
1476 if (ctwindow != pAdapter->ctw)
1477 {
1478 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301479
Jeff Johnson295189b2012-06-20 16:38:30 -07001480 if(pAdapter->ops)
1481 {
1482 NoA.opp_ps = pAdapter->ops;
1483 NoA.ctWindow = pAdapter->ctw;
1484 NoA.duration = 0;
1485 NoA.single_noa_duration = 0;
1486 NoA.interval = 0;
1487 NoA.count = 0;
1488 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1489 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301490
Jeff Johnson295189b2012-06-20 16:38:30 -07001491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1492 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1493 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001494 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001495 NoA.ctWindow, NoA.duration, NoA.interval,
1496 NoA.count, NoA.single_noa_duration,
1497 NoA.psSelection);
1498
1499 sme_p2pSetPs(hHal, &NoA);
1500 }
1501 return 0;
1502 }
1503 }
1504
1505 if (opp_ps != -1)
1506 {
1507 pAdapter->ops = opp_ps;
1508
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301509 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001510 {
1511 NoA.opp_ps = opp_ps;
1512 NoA.ctWindow = pAdapter->ctw;
1513 NoA.duration = 0;
1514 NoA.single_noa_duration = 0;
1515 NoA.interval = 0;
1516 NoA.count = 0;
1517 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1518 NoA.sessionid = pAdapter->sessionId;
1519
1520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1521 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1522 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001523 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001524 NoA.ctWindow, NoA.duration, NoA.interval,
1525 NoA.count, NoA.single_noa_duration,
1526 NoA.psSelection);
1527
1528 sme_p2pSetPs(hHal, &NoA);
1529 }
1530 }
1531 return status;
1532}
1533
1534int hdd_setP2pPs( struct net_device *dev, void *msgData )
1535{
1536 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1537 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1538 VOS_STATUS status = VOS_STATUS_SUCCESS;
1539 tP2pPsConfig NoA;
1540 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1541
1542 NoA.opp_ps = pappNoA->opp_ps;
1543 NoA.ctWindow = pappNoA->ctWindow;
1544 NoA.duration = pappNoA->duration;
1545 NoA.interval = pappNoA->interval;
1546 NoA.count = pappNoA->count;
1547 NoA.single_noa_duration = pappNoA->single_noa_duration;
1548 NoA.psSelection = pappNoA->psSelection;
1549 NoA.sessionid = pAdapter->sessionId;
1550
1551 sme_p2pSetPs(hHal, &NoA);
1552 return status;
1553}
Jeff Johnson295189b2012-06-20 16:38:30 -07001554
1555static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1556{
1557 tANI_U8 sessionType;
1558
1559 switch( type )
1560 {
1561 case NL80211_IFTYPE_AP:
1562 sessionType = WLAN_HDD_SOFTAP;
1563 break;
1564 case NL80211_IFTYPE_P2P_GO:
1565 sessionType = WLAN_HDD_P2P_GO;
1566 break;
1567 case NL80211_IFTYPE_P2P_CLIENT:
1568 sessionType = WLAN_HDD_P2P_CLIENT;
1569 break;
1570 case NL80211_IFTYPE_STATION:
1571 sessionType = WLAN_HDD_INFRA_STATION;
1572 break;
1573 case NL80211_IFTYPE_MONITOR:
1574 sessionType = WLAN_HDD_MONITOR;
1575 break;
1576 default:
1577 sessionType = WLAN_HDD_INFRA_STATION;
1578 break;
1579 }
1580
1581 return sessionType;
1582}
1583
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001584#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1585struct wireless_dev* wlan_hdd_add_virtual_intf(
1586 struct wiphy *wiphy, const char *name,
1587 enum nl80211_iftype type,
1588 u32 *flags, struct vif_params *params )
1589#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1590struct wireless_dev* wlan_hdd_add_virtual_intf(
1591 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1592 u32 *flags, struct vif_params *params )
1593#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001594struct net_device* wlan_hdd_add_virtual_intf(
1595 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1596 u32 *flags, struct vif_params *params )
1597#else
1598int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1599 enum nl80211_iftype type,
1600 u32 *flags, struct vif_params *params )
1601#endif
1602{
1603 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301604 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301605 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001606 ENTER();
1607
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301608 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1609 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301610 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1611 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1612 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001613 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001614 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001615 "interfaces of same type are not supported currently.",__func__, type);
Jeff Johnsond13512a2012-07-17 11:42:19 -07001616 return NULL;
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001617 }
1618
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001619 if (pHddCtx->isLogpInProgress)
1620 {
1621 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1622 "%s:LOGP in Progress. Ignore!!!", __func__);
1623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1624 return NULL;
1625#else
1626 return -EAGAIN;
1627#endif
1628 }
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301629
1630 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1631 pScanInfo = &pHddCtx->scan_info;
1632 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1633 (pHddCtx->scan_info.mScanPending))
1634 {
1635 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1636 eCSR_SCAN_ABORT_DEFAULT);
1637 hddLog(VOS_TRACE_LEVEL_INFO,
1638 "%s: Abort Scan while adding virtual interface",__func__);
1639 }
1640
1641 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05301642 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1643 ((NL80211_IFTYPE_P2P_GO == type) ||
1644 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001645 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001646 /* Generate the P2P Interface Address. this address must be
1647 * different from the P2P Device Address.
1648 */
1649 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1650 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301651 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001652 wlan_hdd_get_session_type(type),
1653 name, p2pDeviceAddress.bytes,
1654 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001655 }
1656 else
1657 {
1658 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1659 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1660 }
1661
1662 if( NULL == pAdapter)
1663 {
1664 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1665#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1666 return NULL;
1667#else
1668 return -EINVAL;
1669#endif
1670 }
1671 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001672#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1673 return pAdapter->dev->ieee80211_ptr;
1674#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001675 return pAdapter->dev;
1676#else
1677 return 0;
1678#endif
1679}
1680
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001681#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1682int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1683#else
Jeff Johnson295189b2012-06-20 16:38:30 -07001684int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001685#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001686{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001687#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1688 struct net_device *dev = wdev->netdev;
1689#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301690 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301691 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301692 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1693 int status;
1694 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001695
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301696 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1697 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1698 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301699 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1700 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001701
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301702 status = wlan_hdd_validate_context(pHddCtx);
1703
1704 if (0 != status)
1705 {
1706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1707 "%s: HDD context is not valid", __func__);
1708 return status;
1709 }
1710
1711 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001712 pVirtAdapter->macAddressCurrent.bytes );
1713
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301714 hdd_stop_adapter( pHddCtx, pVirtAdapter );
1715 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1716 EXIT();
1717 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001718}
1719
1720void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001721 tANI_U32 nFrameLength,
1722 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301723 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07001724{
1725 //Indicate a Frame over Monitor Intf.
1726 int rxstat;
1727 struct sk_buff *skb = NULL;
1728 int needed_headroom = 0;
1729 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
1730 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001731#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001732#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
1733 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
1734#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001735#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001736 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
1737
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001738 if (NULL == pbFrames)
1739 {
1740 hddLog(LOGE, FL("NULL frame pointer"));
1741 return;
1742 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001743
1744 /* room for the radiotap header based on driver features
1745 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
1746 * RX flags.
1747 * */
1748 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
1749
1750 //alloc skb here
1751 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
1752 if (unlikely(NULL == skb))
1753 {
1754 hddLog( LOGW, FL("Unable to allocate skb"));
1755 return;
1756 }
1757 skb_reserve(skb, VPKT_SIZE_BUFFER);
1758 if (unlikely(skb_headroom(skb) < nFrameLength))
1759 {
1760 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
1761 "HDD [%d]: Insufficient headroom, "
1762 "head[%p], data[%p], req[%d]",
1763 __LINE__, skb->head, skb->data, nFrameLength);
1764 kfree_skb(skb);
1765 return ;
1766 }
1767 // actually push the data
1768 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
1769 /* prepend radiotap information */
1770 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
1771 {
1772 hddLog( LOGE, FL("Not Able Add Radio Tap"));
1773 //free skb
1774 kfree_skb(skb);
1775 return ;
1776 }
1777
1778 skb_reset_mac_header( skb );
1779 skb->dev = pMonAdapter->dev;
1780 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07001781 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001782#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07001783#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07001784 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07001785#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08001786#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001787 rxstat = netif_rx_ni(skb);
1788 if( NET_RX_SUCCESS == rxstat )
1789 {
1790 hddLog( LOG1, FL("Success"));
1791 }
1792 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301793 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07001794
1795 return ;
1796}
1797
1798void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301799 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07001800 tANI_U8* pbFrames,
1801 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05301802 tANI_U32 rxChan,
1803 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07001804{
1805 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301806 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07001807 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001808 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07001809 tActionFrmType actionFrmType;
1810 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301811 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05301812 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301813 VOS_STATUS status;
1814 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001815
Arif Hussain6d2a3322013-11-17 19:50:10 -08001816 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001817 __func__, frameType, nFrameLength);
1818
1819 if (NULL == pAdapter)
1820 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001821 hddLog(LOGE, FL("pAdapter is NULL"));
1822 return;
1823 }
1824
1825 if (0 == nFrameLength)
1826 {
1827 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
1828 return;
1829 }
1830
1831 if (NULL == pbFrames)
1832 {
1833 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001834 return;
1835 }
1836
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001837 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
1838 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
1839
1840 /* Get pAdapter from Destination mac address of the frame */
1841 if ((type == SIR_MAC_MGMT_FRAME) &&
1842 (subType != SIR_MAC_MGMT_PROBE_REQ))
1843 {
1844 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
1845 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
1846 if (NULL == pAdapter)
1847 {
1848 /* Under assumtion that we don't receive any action frame
1849 * with BCST as destination we dropping action frame
1850 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08001851 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
1852 MAC_ADDRESS_STR ,
1853 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
1854 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08001855 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07001856 return;
1857 }
1858 }
1859
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001860
Jeff Johnson295189b2012-06-20 16:38:30 -07001861 if (NULL == pAdapter->dev)
1862 {
1863 hddLog( LOGE, FL("pAdapter->dev is NULL"));
1864 return;
1865 }
1866
1867 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1868 {
1869 hddLog( LOGE, FL("pAdapter has invalid magic"));
1870 return;
1871 }
1872
Rashmi Ramannadae90e02013-12-30 21:49:48 +05301873 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1874 if (NULL == pHddCtx)
1875 {
1876 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
1877 return;
1878 }
1879
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001880 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
1881 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001882 {
1883 hdd_adapter_t *pMonAdapter =
1884 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
1885
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07001886 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07001887 {
1888 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
1889 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
1890 pbFrames, frameType);
1891 return;
1892 }
1893 }
1894
1895 //Channel indicated may be wrong. TODO
1896 //Indicate an action frame.
1897 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
1898 {
1899 freq = ieee80211_channel_to_frequency( rxChan,
1900 IEEE80211_BAND_2GHZ);
1901 }
1902 else
1903 {
1904 freq = ieee80211_channel_to_frequency( rxChan,
1905 IEEE80211_BAND_5GHZ);
1906 }
1907
Jeff Johnsone7245742012-09-05 17:12:55 -07001908 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301909 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301910
1911 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001912 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07001913 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001914 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
1915 {
1916 // public action frame
1917 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08001918 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 -08001919 // P2P action frames
1920 {
1921 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08001922 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001923#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001924 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
1925 {
1926 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
1927 actionFrmType);
1928 }
1929 else
1930 {
1931 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
1932 p2p_action_frame_type[actionFrmType]);
1933 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1934 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1935 {
1936 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1937 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001938 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001939 }
1940 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1941 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1942 {
1943 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08001944 hddLog(LOGE,"[P2P State]GO negotiation progress to "
1945 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001946 }
1947 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
1948 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1949 {
1950 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1951 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
1952 " completed state Autonomous GO formation");
1953 }
1954 }
1955#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301956 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
1957 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
1958 {
1959 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1960 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
1961 actionFrmType == WLAN_HDD_INVITATION_REQ ||
1962 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
1963 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
1964 {
1965 hddLog( LOG1, "Extend RoC timer on reception of"
1966 " Action Frame");
1967 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
1968 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
1969 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
1970 else
1971 extend_time = ACTION_FRAME_DEFAULT_WAIT;
1972 if (completion_done(&pAdapter->rem_on_chan_ready_event))
1973 {
1974 vos_timer_stop(
1975 &pRemainChanCtx->hdd_remain_on_chan_timer);
1976 status = vos_timer_start(
1977 &pRemainChanCtx->hdd_remain_on_chan_timer,
1978 extend_time);
1979 if (status != VOS_STATUS_SUCCESS)
1980 {
1981 hddLog( LOGE, "ROC timer start failed");
1982 }
1983 }
1984 else
1985 {
1986 // Buffer Packet
1987 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
1988 {
1989 pRemainChanCtx->action_pkt_buff.frame_length =
1990 nFrameLength;
1991 pRemainChanCtx->action_pkt_buff.freq = freq;
1992 pRemainChanCtx->action_pkt_buff.frame_ptr
1993 = vos_mem_malloc(nFrameLength);
1994 vos_mem_copy(
1995 pRemainChanCtx->action_pkt_buff.frame_ptr,
1996 pbFrames, nFrameLength);
1997 hddLog( LOGE,"%s:"
1998 "Action Pkt Cached successfully !!!", __func__);
1999 }
2000 else
2001 {
2002 hddLog( LOGE,"%s:"
2003 "Frames are pending. dropping frame !!!",
2004 __func__);
2005 }
2006 return;
2007 }
2008 }
2009 }
2010 if (pRemainChanCtx != NULL &&
2011 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2012 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2013 hddLog( LOG1, "%s:"
2014 "Rcvd action frame after timer expired ", __func__);
2015
2016 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) ||
2017 (actionFrmType == WLAN_HDD_GO_NEG_REQ) ||
2018 (actionFrmType == WLAN_HDD_INVITATION_REQ) )
2019 {
2020 pScanInfo = &pHddCtx->scan_info;
2021 if((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2022 {
2023 hddLog(LOGE,"Action frame received when Scanning is in"
2024 " progress. Abort Scan.");
2025 hdd_abort_mac_scan(pAdapter->pHddCtx,
2026 pAdapter->sessionId,
2027 eCSR_SCAN_ABORT_DEFAULT);
2028 }
2029 }
2030 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2031 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2032 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2033 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2034 {
2035 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2036 __func__);
2037 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002038 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002039 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002040#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002041 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 -07002042 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002043 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
2044#ifdef WLAN_FEATURE_TDLS_DEBUG
2045 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2046 MAC_ADDR_ARRAY(mac),rxRssi);
2047#endif
2048 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2049 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002050 }
2051#endif
2052 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002053#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002054 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2055 {
2056 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2057 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2058 {
2059 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2060 actionFrmType);
2061 }
2062 else
2063 {
2064 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2065 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002066 }
2067 }
2068#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002069 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2070 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2071 {
2072 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal, hddWmmDscpToUpMapInfra);
2073 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002074 }
2075
Jeff Johnson295189b2012-06-20 16:38:30 -07002076 //Indicate Frame Over Normal Interface
2077 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2078
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002079#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2080 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2081 pbFrames, nFrameLength,
2082 GFP_ATOMIC );
2083#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002084 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2085 pbFrames, nFrameLength,
2086 GFP_ATOMIC );
2087#else
2088 cfg80211_rx_mgmt( pAdapter->dev, freq,
2089 pbFrames, nFrameLength,
2090 GFP_ATOMIC );
2091#endif //LINUX_VERSION_CODE
2092}
2093
2094/*
2095 * ieee80211_add_rx_radiotap_header - add radiotap header
2096 */
2097static int hdd_wlan_add_rx_radiotap_hdr (
2098 struct sk_buff *skb, int rtap_len, int flag )
2099{
2100 u8 rtap_temp[20] = {0};
2101 struct ieee80211_radiotap_header *rthdr;
2102 unsigned char *pos;
2103 u16 rx_flags = 0;
2104
2105 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2106
2107 /* radiotap header, set always present flags */
2108 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2109 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2110 rthdr->it_len = cpu_to_le16(rtap_len);
2111
2112 pos = (unsigned char *) (rthdr + 1);
2113
2114 /* the order of the following fields is important */
2115
2116 /* IEEE80211_RADIOTAP_FLAGS */
2117 *pos = 0;
2118 pos++;
2119
2120 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2121 /* ensure 2 byte alignment for the 2 byte field as required */
2122 if ((pos - (u8 *)rthdr) & 1)
2123 pos++;
2124 put_unaligned_le16(rx_flags, pos);
2125 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302126
Jeff Johnson295189b2012-06-20 16:38:30 -07002127 // actually push the data
2128 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2129
2130 return 0;
2131}
2132
2133static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2134 hdd_cfg80211_state_t* cfgState,
2135 tANI_BOOLEAN actionSendSuccess )
2136{
2137 struct ieee80211_radiotap_header *rthdr;
2138 unsigned char *pos;
2139 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002140#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002141#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2142 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2143#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002144#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002145
2146 /* 2 Byte for TX flags and 1 Byte for Retry count */
2147 u32 rtHdrLen = sizeof(*rthdr) + 3;
2148
2149 u8 *data;
2150
2151 /* We have to return skb with Data starting with MAC header. We have
2152 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2153 * entire skb->len from skb and then we will push cfgState->buf to skb
2154 * */
2155 if( NULL == skb_pull(skb, skb->len) )
2156 {
2157 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2158 kfree_skb(cfgState->skb);
2159 return;
2160 }
2161
2162 data = skb_push( skb, cfgState->len );
2163
2164 if (data == NULL)
2165 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002166 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002167 kfree_skb( cfgState->skb );
2168 return;
2169 }
2170
2171 memcpy( data, cfgState->buf, cfgState->len );
2172
2173 /* send frame to monitor interfaces now */
2174 if( skb_headroom(skb) < rtHdrLen )
2175 {
2176 hddLog( LOGE, FL("No headroom for rtap header"));
2177 kfree_skb(cfgState->skb);
2178 return;
2179 }
2180
2181 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2182
2183 memset( rthdr, 0, rtHdrLen );
2184 rthdr->it_len = cpu_to_le16( rtHdrLen );
2185 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2186 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2187 );
2188
2189 pos = (unsigned char *)( rthdr+1 );
2190
2191 // Fill TX flags
2192 *pos = actionSendSuccess;
2193 pos += 2;
2194
2195 // Fill retry count
2196 *pos = 0;
2197 pos++;
2198
2199 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002200 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002201 skb->pkt_type = PACKET_OTHERHOST;
2202 skb->protocol = htons(ETH_P_802_2);
2203 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002204#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002205#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002206 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002207#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002208#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002209 if (in_interrupt())
2210 netif_rx( skb );
2211 else
2212 netif_rx_ni( skb );
2213
2214 /* Enable Queues which we have disabled earlier */
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302215 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002216
2217}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302218