blob: cbff04a8bf8f90ab1f8cabbe35a5f58846739f90 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302 * Copyright (c) 2012-2015, 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
Jeff Johnson295189b2012-06-20 16:38:30 -070034
35 ========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070036
37#include <wlan_hdd_includes.h>
38#include <wlan_hdd_hostapd.h>
39#include <net/cfg80211.h>
40#include "sme_Api.h"
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -070041#include "sme_QosApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070042#include "wlan_hdd_p2p.h"
43#include "sapApi.h"
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053044#include "wlan_hdd_main.h"
Daram Sudha1f7e0e92013-12-17 07:52:31 +053045#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070046#include <linux/netdevice.h>
47#include <linux/skbuff.h>
48#include <linux/etherdevice.h>
49#include <net/ieee80211_radiotap.h>
Hoonki Lee1090c6a2013-01-16 17:40:54 -080050#ifdef FEATURE_WLAN_TDLS
51#include "wlan_hdd_tdls.h"
52#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053053#include "wlan_hdd_trace.h"
54#include "vos_types.h"
55#include "vos_trace.h"
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +053056#include "vos_sched.h"
57
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080058//Ms to Micro Sec
59#define MS_TO_MUS(x) ((x)*1000);
Daram Sudha1f7e0e92013-12-17 07:52:31 +053060tANI_U8* hdd_getActionString( tANI_U16 MsgType )
61{
62 switch (MsgType)
63 {
64 CASE_RETURN_STRING(SIR_MAC_ACTION_SPECTRUM_MGMT);
65 CASE_RETURN_STRING(SIR_MAC_ACTION_QOS_MGMT);
66 CASE_RETURN_STRING(SIR_MAC_ACTION_DLP);
67 CASE_RETURN_STRING(SIR_MAC_ACTION_BLKACK);
68 CASE_RETURN_STRING(SIR_MAC_ACTION_PUBLIC_USAGE);
69 CASE_RETURN_STRING(SIR_MAC_ACTION_RRM);
70 CASE_RETURN_STRING(SIR_MAC_ACTION_FAST_BSS_TRNST);
71 CASE_RETURN_STRING(SIR_MAC_ACTION_HT);
72 CASE_RETURN_STRING(SIR_MAC_ACTION_SA_QUERY);
73 CASE_RETURN_STRING(SIR_MAC_ACTION_PROT_DUAL_PUB);
74 CASE_RETURN_STRING(SIR_MAC_ACTION_WNM);
75 CASE_RETURN_STRING(SIR_MAC_ACTION_UNPROT_WNM);
76 CASE_RETURN_STRING(SIR_MAC_ACTION_TDLS);
77 CASE_RETURN_STRING(SIR_MAC_ACITON_MESH);
78 CASE_RETURN_STRING(SIR_MAC_ACTION_MULTIHOP);
79 CASE_RETURN_STRING(SIR_MAC_SELF_PROTECTED);
80 CASE_RETURN_STRING(SIR_MAC_ACTION_WME);
81 CASE_RETURN_STRING(SIR_MAC_ACTION_VHT);
82 default:
83 return ("UNKNOWN");
84 }
85}
86
87
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070088#ifdef WLAN_FEATURE_P2P_DEBUG
89#define MAX_P2P_ACTION_FRAME_TYPE 9
90const char *p2p_action_frame_type[]={"GO Negotiation Request",
91 "GO Negotiation Response",
92 "GO Negotiation Confirmation",
93 "P2P Invitation Request",
94 "P2P Invitation Response",
95 "Device Discoverability Request",
96 "Device Discoverability Response",
97 "Provision Discovery Request",
98 "Provision Discovery Response"};
99
100/* We no need to protect this variable since
101 * there is no chance of race to condition
102 * and also not make any complicating the code
103 * just for debugging log
104 */
105tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
106
107#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800108#ifdef WLAN_FEATURE_TDLS_DEBUG
109#define MAX_TDLS_ACTION_FRAME_TYPE 11
110const char *tdls_action_frame_type[] = {"TDLS Setup Request",
111 "TDLS Setup Response",
112 "TDLS Setup Confirm",
113 "TDLS Teardown",
114 "TDLS Peer Traffic Indication",
115 "TDLS Channel Switch Request",
116 "TDLS Channel Switch Response",
117 "TDLS Peer PSM Request",
118 "TDLS Peer PSM Response",
119 "TDLS Peer Traffic Response",
120 "TDLS Discovery Request" };
121#endif
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700122
Jeff Johnson295189b2012-06-20 16:38:30 -0700123extern struct net_device_ops net_ops_struct;
124
125static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
126 int rtap_len, int flag );
127
128static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
129 hdd_cfg80211_state_t* cfgState,
130 tANI_BOOLEAN actionSendSuccess );
131
132static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Rashmi Ramannac7744532013-10-06 16:49:08 +0530133 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -0700134 tANI_U8* pbFrames,
135 tANI_U8 frameType );
vamsi9bd92b72013-12-26 14:11:29 +0530136
137static v_BOOL_t hdd_p2p_is_action_type_rsp( const u8 *buf )
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530138{
vamsi9bd92b72013-12-26 14:11:29 +0530139 tActionFrmType actionFrmType;
140 const u8 *ouiPtr;
141
142 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
143 WLAN_HDD_PUBLIC_ACTION_FRAME ) {
144 return VOS_FALSE;
145 }
146
147 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] !=
148 WLAN_HDD_VENDOR_SPECIFIC_ACTION ) {
149 return VOS_FALSE;
150 }
151
152 ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET];
153
154 if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) {
155 return VOS_FALSE;
156 }
157
158 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] !=
159 WLAN_HDD_WFA_P2P_OUI_TYPE ) {
160 return VOS_FALSE;
161 }
162
Ahmad Kholaife5ec2cd2014-03-19 13:22:04 +0530163 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
vamsi9bd92b72013-12-26 14:11:29 +0530164 if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
165 actionFrmType != WLAN_HDD_GO_NEG_REQ &&
166 actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
167 actionFrmType != WLAN_HDD_PROV_DIS_REQ )
168 return VOS_TRUE;
169 else
170 return VOS_FALSE;
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530171}
Jeff Johnson295189b2012-06-20 16:38:30 -0700172
Jeff Johnson295189b2012-06-20 16:38:30 -0700173eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
174 eHalStatus status )
175{
176 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700177 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
178 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530179 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700180
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530181 if (pHddCtx == NULL)
182 {
183 hddLog(LOGE, "%s: Hdd Context is NULL", __func__);
184 return eHAL_STATUS_FAILURE;
185 }
186 if (pRemainChanCtx == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700187 {
188 hddLog( LOGW,
189 "%s: No Rem on channel pending for which Rsp is received", __func__);
190 return eHAL_STATUS_SUCCESS;
191 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530192
193 mutex_lock(&pHddCtx->roc_lock);
Rashmi Ramannac7744532013-10-06 16:49:08 +0530194 hddLog( VOS_TRACE_LEVEL_INFO,
195 "Received ROC rsp (request type %d, channel %d, cookie %llu",
196 pRemainChanCtx->rem_on_chan_request,
197 pRemainChanCtx->chan.center_freq,
198 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700199 cfgState->remain_on_chan_ctx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530200 vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
201 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530202 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530203 if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
Jeff Johnson295189b2012-06-20 16:38:30 -0700204 {
205 if( cfgState->buf )
206 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530207 hddLog( LOGP,
Jeff Johnson295189b2012-06-20 16:38:30 -0700208 "%s: We need to receive yet an ack from one of tx packet",
209 __func__);
210 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800211 cfg80211_remain_on_channel_expired(
212#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
213 pRemainChanCtx->dev->ieee80211_ptr,
214#else
215 pRemainChanCtx->dev,
216#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700217 pRemainChanCtx->cookie,
218 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700219#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
220 pRemainChanCtx->chan_type,
221#endif
222 GFP_KERNEL);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530223 pAdapter->lastRocTs = vos_timer_get_system_time();
Jeff Johnson295189b2012-06-20 16:38:30 -0700224 }
225
Jeff Johnson295189b2012-06-20 16:38:30 -0700226
227 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700228 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
229 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700230 )
231 {
232 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800233 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
234 {
235 sme_DeregisterMgmtFrame(
236 hHal, sessionId,
237 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
238 NULL, 0 );
239 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700240 }
241 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
242 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
243 )
244 {
245 WLANSAP_DeRegisterMgmtFrame(
246 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
247 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
248 NULL, 0 );
249 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530250 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
251 && pRemainChanCtx->action_pkt_buff.frame_length != 0)
252 {
253 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
254 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800255 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800256 pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 complete(&pAdapter->cancel_rem_on_chan_var);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530258 pAdapter->is_roc_inprogress = FALSE;
259 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700260 return eHAL_STATUS_SUCCESS;
261}
262
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530263VOS_STATUS wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700264{
Jeff Johnson295189b2012-06-20 16:38:30 -0700265 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530266 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530267 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700268 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700269
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530270 if (NULL == pHddCtx)
271 {
272 hddLog(LOGE, "%s: HddCtx is NULL", __func__);
273 return VOS_STATUS_E_FAILURE;
274 }
275
276 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700277 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530279 if(VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
280 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
281 {
282 hddLog(VOS_TRACE_LEVEL_INFO,
283 "Cancel Existing ROC (cookie=%llu)",
284 cfgState->remain_on_chan_ctx->cookie);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700285
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530286 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
287 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530288 /* Wait till remain on channel ready indication before issuing cancel
289 * remain on channel request, otherwise if remain on channel not
290 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700291 * will be in unknown state.
292 */
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530293 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress != TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700294 {
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530295 status = wait_for_completion_interruptible_timeout(
296 &pAdapter->rem_on_chan_ready_event,
297 msecs_to_jiffies(WAIT_REM_CHAN_READY));
298 if (0 >= status)
299 {
300 hddLog( LOGE,
301 "%s: timeout waiting for remain on channel"
302 " ready indication %d",
303 __func__, status);
304 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
305 mutex_unlock(&pHddCtx->roc_lock);
306 return VOS_STATUS_E_FAILURE;
307 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700308
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530309 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
310 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
Mahesh A Saptasgar3f692752014-11-17 16:13:35 +0530311 mutex_unlock(&pHddCtx->roc_lock);
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530312
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530313 /* Issue abort remain on chan request to sme.
314 * The remain on channel callback will make sure the remain_on_chan
315 * expired event is sent.
316 */
317 if (( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
318 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
319 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ))
320 {
321 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
Jeff Johnson295189b2012-06-20 16:38:30 -0700322 pAdapter->sessionId );
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530323 }
324 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
325 (WLAN_HDD_P2P_GO == pAdapter->device_mode))
326 {
327 WLANSAP_CancelRemainOnChannel(
328 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
329 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700330
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530331 status = wait_for_completion_interruptible_timeout(
332 &pAdapter->cancel_rem_on_chan_var,
333 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
334 if (0 >= status)
335 {
336 hddLog( LOGE,
337 "%s: timeout waiting for cancel remain on channel"
338 " ready indication %d",
339 __func__, status);
340 }
341 hdd_allow_suspend();
342 }
343 else
344 {
345 hddLog( LOG1,
346 "ROC timer cancellation in progress,"
347 " wait for completion");
348 mutex_unlock(&pHddCtx->roc_lock);
349 status = wait_for_completion_interruptible_timeout(
350 &pAdapter->cancel_rem_on_chan_var,
351 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
352 if (0 >= status)
353 {
354 hddLog( LOGE,
355 "%s:wait on cancel_rem_on_chan_var failed %d",
356 __func__, status);
357 return VOS_STATUS_E_FAILURE;
358 }
359 return VOS_STATUS_SUCCESS;
360 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700361 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530362 else
363 {
364 hddLog(LOG1,
365 "%s: remain_on_chan_ctx is NULL", __func__);
366 mutex_unlock(&pHddCtx->roc_lock);
367 }
368 return VOS_STATUS_SUCCESS;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700369}
370
371int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
372{
373 int status = 0;
374 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
375
376 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
377 {
378 //Cancel Existing Remain On Channel
379 //If no action frame is pending
380 if( cfgState->remain_on_chan_ctx != NULL)
381 {
382 //Check whether Action Frame is pending or not
383 if( cfgState->buf == NULL)
384 {
385 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
386 }
387 else
388 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530389 hddLog(VOS_TRACE_LEVEL_DEBUG,
390 "Cannot Cancel Existing Remain on Channel");
Jeff Johnson32d95a32012-09-10 13:15:23 -0700391 status = -EBUSY;
392 }
393 }
394 }
395 return status;
396}
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530397void wlan_hdd_remain_on_chan_timeout(void *data)
398{
399 hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
400 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
401 hdd_cfg80211_state_t *cfgState;
402 if ( NULL == pAdapter )
403 {
404 hddLog( LOGE, FL("pAdapter is NULL !!!"));
405 return;
406 }
407 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
408 pRemainChanCtx = cfgState->remain_on_chan_ctx;
409 if (NULL == pRemainChanCtx)
410 {
411 hddLog( LOGE, FL("No Remain on channel is pending"));
412 return;
413 }
414 if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
415 {
416 hddLog( LOGE, FL("Cancellation already in progress"));
417 return;
418 }
419
420 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
421 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
422 hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
423 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
424 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
425 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
426 )
427 {
428 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
429 pAdapter->sessionId );
430 }
431 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
432 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
433 )
434 {
435 WLANSAP_CancelRemainOnChannel(
436 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
437 }
438 hdd_allow_suspend();
439}
Jeff Johnson32d95a32012-09-10 13:15:23 -0700440
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530441static int wlan_hdd_p2p_start_remain_on_channel(
442 hdd_adapter_t *pAdapter)
443{
444 VOS_STATUS status = VOS_STATUS_SUCCESS;
445 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
446 hdd_adapter_t *pAdapter_temp;
447 v_BOOL_t isGoPresent = VOS_FALSE;
448 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
449 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
450 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
451 rem_on_channel_request_type_t request_type = pRemainChanCtx->rem_on_chan_request;
452
453 /* Initialize Remain on chan timer */
454 status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
455 VOS_TIMER_TYPE_SW,
456 wlan_hdd_remain_on_chan_timeout,
457 pAdapter);
458 if (status != VOS_STATUS_SUCCESS)
459 {
460 hddLog(VOS_TRACE_LEVEL_ERROR,
461 "%s: Not able to initalize remain_on_chan timer", __func__);
462 }
463 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
464 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
465 {
466 pAdapter_temp = pAdapterNode->pAdapter;
467 if (WLAN_HDD_P2P_GO == pAdapter_temp->device_mode)
468 {
469 isGoPresent = VOS_TRUE;
470 }
471 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
472 pAdapterNode = pNext;
473 }
474 hdd_prevent_suspend();
475 //call sme API to start remain on channel.
476 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
477 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
478 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
479 )
480 {
481 tANI_U8 sessionId = pAdapter->sessionId;
482 //call sme API to start remain on channel.
483 if (eHAL_STATUS_SUCCESS != sme_RemainOnChannel(
484 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
485 pRemainChanCtx->chan.hw_value, pRemainChanCtx->duration,
486 wlan_hdd_remain_on_channel_callback, pAdapter,
487 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE))
488 {
489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
490 FL(" RemainOnChannel returned fail"));
491 cfgState->remain_on_chan_ctx = NULL;
492 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
493 vos_mem_free (pRemainChanCtx);
494 hdd_allow_suspend();
495 return -EINVAL;
496 }
497
498 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
499 {
500 if( eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame(
501 WLAN_HDD_GET_HAL_CTX(pAdapter),
502 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
503 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ))
504 {
505 hddLog(VOS_TRACE_LEVEL_ERROR, "sme_RegisterMgmtFrame returned fail");
506 }
507 }
508
509 }
510 else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
511 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
512 )
513 {
514 //call sme API to start remain on channel.
515 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
516 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
517 pRemainChanCtx->chan.hw_value, pRemainChanCtx->duration,
518 wlan_hdd_remain_on_channel_callback, pAdapter ))
519
520 {
521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
522 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
523 cfgState->remain_on_chan_ctx = NULL;
524 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
525 vos_mem_free (pRemainChanCtx);
526 hdd_allow_suspend();
527 return -EINVAL;
528 }
529
530
531 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
532 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
533 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
534 NULL, 0 ))
535 {
536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
537 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
538 WLANSAP_CancelRemainOnChannel(
539 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
540 hdd_allow_suspend();
541 return -EINVAL;
542 }
543
544 }
545
546 pAdapter->is_roc_inprogress = TRUE;
547 return 0;
548}
549
550
Jeff Johnson32d95a32012-09-10 13:15:23 -0700551static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
552 struct net_device *dev,
553 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700554#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700555 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700556#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700557 unsigned int duration, u64 *cookie,
558 rem_on_channel_request_type_t request_type )
559{
560 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
561 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
562 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530563 hdd_context_t *pHddCtx = NULL;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530564 VOS_STATUS checkReadyInd;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530565 hdd_adapter_t *pStaAdapter;
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530566 int status = 0;
567
568 if (NULL == pAdapter)
569 {
570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
571 "%s: HDD adapter is Null", __func__);
572 return -ENODEV;
573 }
574
575 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
576 status = wlan_hdd_validate_context(pHddCtx);
577
578 if (0 != status)
579 {
580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
581 "%s: HDD context is not valid", __func__);
582 return status;
583 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530584
Jeff Johnson32d95a32012-09-10 13:15:23 -0700585 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
586 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700587#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530588 hddLog(VOS_TRACE_LEVEL_INFO,
589 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
590 " request type %d, cookie %llu",
591 chan->hw_value, chan->center_freq, channel_type, duration,
592 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700593#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530594 hddLog(VOS_TRACE_LEVEL_INFO,
595 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
596 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
597 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700598#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700599 //Cancel existing remain On Channel if any
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530600 checkReadyInd = wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
601 if (VOS_STATUS_SUCCESS != checkReadyInd)
602 {
603 hddLog( LOGE, FL("Cancel Roc in progress"));
604 return -EBUSY;
605 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700606
Jeff Johnsone7245742012-09-05 17:12:55 -0700607 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700608 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700609 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700610 * channel requets when Load/Unload is in progress*/
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530611 if(hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx))
Jeff Johnson295189b2012-06-20 16:38:30 -0700612 {
613 hddLog( LOGE,
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530614 "%s: Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700615 return -EBUSY;
616 }
617
618 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
619 if( NULL == pRemainChanCtx )
620 {
621 hddLog(VOS_TRACE_LEVEL_FATAL,
622 "%s: Not able to allocate memory for Channel context",
623 __func__);
624 return -ENOMEM;
625 }
626
627 vos_mem_copy( &pRemainChanCtx->chan, chan,
628 sizeof(struct ieee80211_channel) );
629
Yue Maf49ba872013-08-19 12:04:25 -0700630#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700631 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700632#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700633 pRemainChanCtx->duration = duration;
634 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800635 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700636 pRemainChanCtx->cookie = *cookie;
637 pRemainChanCtx->rem_on_chan_request = request_type;
638 cfgState->remain_on_chan_ctx = pRemainChanCtx;
639 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530640 pRemainChanCtx->action_pkt_buff.freq = 0;
641 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
642 pRemainChanCtx->action_pkt_buff.frame_length = 0;
643 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530644 pRemainChanCtx->is_pending_roc_cancelled = FALSE;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530645
Jeff Johnson295189b2012-06-20 16:38:30 -0700646 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
647
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530648 if (REMAIN_ON_CHANNEL_REQUEST == request_type)
Jeff Johnson295189b2012-06-20 16:38:30 -0700649 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530650 pStaAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
651 if((NULL != pStaAdapter)&&
652 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pStaAdapter)))
Sushant Kaushik298a8592014-12-09 17:34:07 +0530653 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530654 if (pAdapter->lastRocTs !=0 &&
655 ((vos_timer_get_system_time() - pAdapter->lastRocTs )
656 < pHddCtx->cfg_ini->gP2PListenDeferInterval))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530657 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530658 if (pRemainChanCtx->duration > HDD_P2P_MAX_ROC_DURATION)
659 pRemainChanCtx->duration = HDD_P2P_MAX_ROC_DURATION;
660 schedule_delayed_work(&pAdapter->roc_work,
661 msecs_to_jiffies(pHddCtx->cfg_ini->gP2PListenDeferInterval));
662 hddLog(VOS_TRACE_LEVEL_INFO, "Defer interval is %hu, pAdapter %p",
663 pHddCtx->cfg_ini->gP2PListenDeferInterval, pAdapter);
664 return 0;
Rashmi Ramannac7744532013-10-06 16:49:08 +0530665 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800666 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700667 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530668
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530669 return wlan_hdd_p2p_start_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700670}
671
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530672int __wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800673#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
674 struct wireless_dev *wdev,
675#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700676 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800677#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700678 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700679#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700680 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700681#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700682 unsigned int duration, u64 *cookie )
683{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800684#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
685 struct net_device *dev = wdev->netdev;
686#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530687 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
688
689 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
690 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
691 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Jeff Johnson295189b2012-06-20 16:38:30 -0700692 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700693 chan,
694#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
695 channel_type,
696#endif
697 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700698 REMAIN_ON_CHANNEL_REQUEST);
699}
700
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530701int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
702#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
703 struct wireless_dev *wdev,
704#else
705 struct net_device *dev,
706#endif
707 struct ieee80211_channel *chan,
708#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
709 enum nl80211_channel_type channel_type,
710#endif
711 unsigned int duration, u64 *cookie )
712{
713 int ret;
714
715 vos_ssr_protect(__func__);
716 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
717#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
718 wdev,
719#else
720 dev,
721#endif
722 chan,
723#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
724 channel_type,
725#endif
726 duration, cookie);
727 vos_ssr_unprotect(__func__);
728
729 return ret;
730}
731
732
Jeff Johnson295189b2012-06-20 16:38:30 -0700733void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
734{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530735 hdd_cfg80211_state_t *cfgState = NULL;
736 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530737 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530738 if (NULL == pAdapter)
739 {
740 hddLog(LOGE, FL("pAdapter is NULL"));
741 return;
742 }
743 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
744 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530745 hddLog( LOG1, "Ready on chan ind");
Jeff Johnson295189b2012-06-20 16:38:30 -0700746 if( pRemainChanCtx != NULL )
747 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530748 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
749 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
750 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530751 //start timer for actual duration
752 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
753 (pRemainChanCtx->duration));
754 if (VOS_STATUS_SUCCESS!=status)
755 {
756 hddLog( LOGE, FL("Remain on Channel timer start failed"));
757 }
758 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700759 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800760 cfg80211_ready_on_channel(
761#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
762 pAdapter->dev->ieee80211_ptr,
763#else
764 pAdapter->dev,
765#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800766 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700767 &pRemainChanCtx->chan,
768#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
769 pRemainChanCtx->chan_type,
770#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700771 pRemainChanCtx->duration, GFP_KERNEL );
772 }
773#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530774 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700775 {
776 complete(&pAdapter->offchannel_tx_event);
777 }
778#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530779 // Check for cached action frame
780 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
781 {
782#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
783 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
784 pRemainChanCtx->action_pkt_buff.freq, 0,
785 pRemainChanCtx->action_pkt_buff.frame_ptr,
786 pRemainChanCtx->action_pkt_buff.frame_length,
787 GFP_ATOMIC );
788#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
789 cfg80211_rx_mgmt( pAdapter->dev,
790 pRemainChanCtx->action_pkt_buff.freq, 0,
791 pRemainChanCtx->action_pkt_buff.frame_ptr,
792 pRemainChanCtx->action_pkt_buff.frame_length,
793 GFP_ATOMIC );
794#else
795 cfg80211_rx_mgmt( pAdapter->dev,
796 pRemainChanCtx->action_pkt_buff.freq,
797 pRemainChanCtx->action_pkt_buff.frame_ptr,
798 pRemainChanCtx->action_pkt_buff.frame_length,
799 GFP_ATOMIC );
800#endif //LINUX_VERSION_CODE
801 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
802 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
803 pRemainChanCtx->action_pkt_buff.frame_length = 0;
804 pRemainChanCtx->action_pkt_buff.freq = 0;
805 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
806 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530807 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
808 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700809 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530810 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
811 {
812 /* since pRemainChanCtx->is_pending_roc_cancelled is
813 * set, it means Cancel Reamain on channel command is
814 * pending because remain on channel event was not
815 * ready when cancel ROC was issued.So issue
816 * cancel ROC now.
817 */
818 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
819 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700820 }
821 else
822 {
823 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
824 }
825 return;
826}
827
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530828int __wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800829#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
830 struct wireless_dev *wdev,
831#else
832 struct net_device *dev,
833#endif
834 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700835{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800836#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
837 struct net_device *dev = wdev->netdev;
838#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700839 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700840 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530841 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530842 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
843 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530844 u64 cookie_dummy;
845 cookie_dummy = cookie << 32;
846 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
847 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
848 pAdapter->sessionId, cookie_dummy));
849 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -0700850
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530851 status = wlan_hdd_validate_context(pHddCtx);
852
853 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700854 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
856 "%s: HDD context is not valid", __func__);
857 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700858 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530859 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
860
Jeff Johnson295189b2012-06-20 16:38:30 -0700861 /* FIXME cancel currently running remain on chan.
862 * Need to check cookie and cancel accordingly
863 */
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530864 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700865 if( (cfgState->remain_on_chan_ctx == NULL) ||
866 (cfgState->remain_on_chan_ctx->cookie != cookie) )
867 {
868 hddLog( LOGE,
869 "%s: No Remain on channel pending with specified cookie value",
870 __func__);
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530871 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700872 return -EINVAL;
873 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530874 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
875 {
876 /* wait until remain on channel ready event received
877 * for already issued remain on channel request */
878 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
879 msecs_to_jiffies(WAIT_REM_CHAN_READY));
880 if (0 >= status)
881 {
882 hddLog( LOGE,
883 "%s: timeout waiting for remain on channel ready indication %d",
884 __func__, status);
885 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530886 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530887 return 0;
888
889 }
890 }
891 else
892 {
893 hddLog( LOG1, FL("Cancel ROC event is already pending, "
894 "waiting for ready on channel indication.") );
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530895 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530896 return 0;
897 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530898 if (NULL != cfgState->remain_on_chan_ctx)
899 {
900 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
901 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
902 {
903 hddLog( LOG1,
904 FL("ROC timer cancellation in progress,"
905 " wait for completion"));
906 status = wait_for_completion_interruptible_timeout(
907 &pAdapter->cancel_rem_on_chan_var,
908 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
909 if (0 >= status)
910 {
911 hddLog( LOGE,
912 "%s:wait on cancel_rem_on_chan_var failed %d",
913 __func__, status);
914 }
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530915 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530916 return 0;
917 }
918 else
919 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
920 }
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530921 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700922 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
923 /* Issue abort remain on chan request to sme.
924 * The remain on channel callback will make sure the remain_on_chan
925 * expired event is sent.
926 */
927 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700928 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
929 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700930 )
931 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530932 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
934 sessionId );
935 }
936 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
937 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
938 )
939 {
940 WLANSAP_CancelRemainOnChannel(
941 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
942 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530943 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700944 {
945 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
946 __func__, pAdapter->device_mode);
947 return -EIO;
948 }
c_hpothu7f63e882013-10-02 19:13:35 +0530949 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700950 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +0530951 if (0 >= status)
952 {
953 hddLog( LOGE,
954 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
955 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530956 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700957 return 0;
958}
959
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530960int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800961#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530962 struct wireless_dev *wdev,
963#else
964 struct net_device *dev,
965#endif
966 u64 cookie )
967{
968 int ret;
969
970 vos_ssr_protect(__func__);
971 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
972#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
973 wdev,
974#else
975 dev,
976#endif
977 cookie);
978 vos_ssr_unprotect(__func__);
979
980 return ret;
981}
982
983
984#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
985int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800986 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700987#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800988 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700989 bool channel_type_valid,
990#endif
991 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800992 const u8 *buf, size_t len, bool no_cck,
993 bool dont_wait_for_ack, u64 *cookie )
994#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530995int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700996 struct ieee80211_channel *chan, bool offchan,
997 enum nl80211_channel_type channel_type,
998 bool channel_type_valid, unsigned int wait,
999 const u8 *buf, size_t len, bool no_cck,
1000 bool dont_wait_for_ack, u64 *cookie )
1001#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301002int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001003 struct ieee80211_channel *chan, bool offchan,
1004 enum nl80211_channel_type channel_type,
1005 bool channel_type_valid, unsigned int wait,
1006 const u8 *buf, size_t len, u64 *cookie )
1007#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301008int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001009 struct ieee80211_channel *chan,
1010 enum nl80211_channel_type channel_type,
1011 bool channel_type_valid,
1012 const u8 *buf, size_t len, u64 *cookie )
1013#endif //LINUX_VERSION_CODE
1014{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001015#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1016 struct net_device *dev = wdev->netdev;
1017#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001018 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301019 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1020 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
1021 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -07001022 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
1023 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
Mukul Sharma1e5d0b72014-07-01 19:22:21 +05301024 tActionFrmType actionFrmType = WLAN_HDD_ACTION_FRM_TYPE_MAX;
Jeff Johnsone7245742012-09-05 17:12:55 -07001025 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301026 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -07001027
Jeff Johnson295189b2012-06-20 16:38:30 -07001028#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1029 hdd_adapter_t *goAdapter;
1030#endif
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301031
1032 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301033 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
1034 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301035 status = wlan_hdd_validate_context(pHddCtx);
1036
1037 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001038 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1040 "%s: HDD context is not valid", __func__);
1041 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001042 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301043
c_hpothu7f63e882013-10-02 19:13:35 +05301044 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
1045 __func__, pAdapter->device_mode, type);
1046
1047
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001048 if ((type == SIR_MAC_MGMT_FRAME) &&
1049 (subType == SIR_MAC_MGMT_ACTION) &&
1050 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
1051 {
1052 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301053#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001054 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001055 {
1056 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
1057 actionFrmType);
1058 }
1059 else
1060 {
1061 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
1062 p2p_action_frame_type[actionFrmType]);
1063 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1064 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1065 {
1066 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1067 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001068 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001069 }
1070 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1071 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1072 {
1073 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1074 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
1075 " completed state");
1076 }
1077 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001078#endif
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301079 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001080
Jeff Johnsone7245742012-09-05 17:12:55 -07001081#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1082 noack = dont_wait_for_ack;
1083#endif
1084
1085 //If the wait is coming as 0 with off channel set
1086 //then set the wait to 200 ms
1087 if (offchan && !wait)
1088 wait = ACTION_FRAME_DEFAULT_WAIT;
1089
Jeff Johnson295189b2012-06-20 16:38:30 -07001090 //Call sme API to send out a action frame.
1091 // OR can we send it directly through data path??
1092 // After tx completion send tx status back.
1093 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1094 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1095 )
1096 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001097 if (type == SIR_MAC_MGMT_FRAME)
1098 {
1099 if (subType == SIR_MAC_MGMT_PROBE_RSP)
1100 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301101 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -07001102 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301103 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001104 goto err_rem_channel;
1105 }
1106 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
1107 (subType == SIR_MAC_MGMT_DEAUTH))
1108 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001109 /* During EAP failure or P2P Group Remove supplicant
1110 * is sending del_station command to driver. From
1111 * del_station function, Driver will send deauth frame to
1112 * p2p client. No need to send disassoc frame from here.
1113 * so Drop the frame here and send tx indication back to
1114 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -07001115 */
1116 tANI_U8 dstMac[ETH_ALEN] = {0};
1117 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07001118 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001119 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -08001120 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001121 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08001122 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001123 goto err_rem_channel;
1124 }
1125 }
1126 }
1127
1128 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001129 {
1130 if ( !noack )
1131 {
1132 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1133 __func__);
1134 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1135 }
1136 else
1137 {
1138 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1139 __func__);
1140 return -EBUSY;
1141 }
1142 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001143
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301144 if( subType == SIR_MAC_MGMT_ACTION)
1145 {
1146 hddLog( LOG1, "Action frame tx request : %s",
1147 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1148 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001149
1150#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1151 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1152
1153 //If GO adapter exists and operating on same frequency
1154 //then we will not request remain on channel
1155 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1156 == goAdapter->sessionCtx.ap.operatingChannel ) )
1157 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301158 /* if GO exist and is not off channel
1159 * wait time should be zero.
1160 */
1161 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001162 goto send_frame;
1163 }
1164#endif
1165
1166#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1167 if( offchan && wait)
1168 {
1169 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301170 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001171 // In case of P2P Client mode if we are already
1172 // on the same channel then send the frame directly
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301173 mutex_lock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301174 if( (cfgState->remain_on_chan_ctx != NULL) &&
1175 (cfgState->current_freq == chan->center_freq)
1176 )
1177 {
1178 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1179 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301180 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301181 /* Some times FW is taking almost 500 msec for
1182 * full 15 retries, which leads to ROC expiration
1183 * by the time peer gets response from other peer.
1184 * Therefore as part of temporary fix , in host
1185 * ROC time is extended. For frames where we are
1186 * expecting response from peer , its extended by
1187 * 500 msec to make ROC wait time as 1 sec and
1188 * in other cases its extended by 300 msec to make
1189 * total ROC wait as 500 msec.
1190 * TODO: FW needs to fix as why 15 retry is taking
1191 * such long time.
1192 */
1193 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1194 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1195 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1196 wait = wait + ACTION_FRAME_RSP_WAIT;
1197 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1198 actionFrmType == WLAN_HDD_INVITATION_RESP )
1199 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301200 vos_timer_stop(
1201 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1202 status = vos_timer_start(
1203 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1204 wait);
1205 if ( status != VOS_STATUS_SUCCESS )
vamsida0e5ab2013-12-26 14:33:27 +05301206 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301207 hddLog( LOGE, "Remain on Channel timer start failed");
1208 }
1209
1210 hddLog(VOS_TRACE_LEVEL_INFO,
1211 "action frame: extending the wait time %u",
1212 wait);
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301213 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301214 goto send_frame;
1215 }
1216 else
1217 {
1218 if ( TRUE ==
1219 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1220 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301221 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301222 hddLog(VOS_TRACE_LEVEL_INFO,
1223 "action frame tx: waiting for completion of ROC ");
1224
1225 status = wait_for_completion_interruptible_timeout(
1226 &pAdapter->cancel_rem_on_chan_var,
1227 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1228 if (0 >= status)
1229 {
1230 hddLog( LOGE,
1231 "%s:wait on cancel_rem_on_chan_var failed %d",
1232 __func__, status);
1233 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301234 goto bypass_lock;
vamsida0e5ab2013-12-26 14:33:27 +05301235 }
1236 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301237 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301238 mutex_unlock(&pHddCtx->roc_lock);
1239bypass_lock:
Rashmi Ramannac7744532013-10-06 16:49:08 +05301240 hddLog(VOS_TRACE_LEVEL_INFO,
1241 "action frame: Request ROC for wait time %u", wait);
Jeff Johnson295189b2012-06-20 16:38:30 -07001242 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001243 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001244 chan,
1245#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1246 channel_type,
1247#endif
1248 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301249 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001250
1251 if(0 != status)
1252 {
1253 if( (-EBUSY == status) &&
1254 (cfgState->current_freq == chan->center_freq) )
1255 {
1256 goto send_frame;
1257 }
1258 goto err_rem_channel;
1259 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001260 /* Wait for driver to be ready on the requested channel */
1261 status = wait_for_completion_interruptible_timeout(
1262 &pAdapter->offchannel_tx_event,
1263 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301264 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001265 {
c_hpothu7f63e882013-10-02 19:13:35 +05301266 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001267 goto err_rem_channel;
1268 }
1269 }
1270 else if ( offchan )
1271 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001272 /* Check before sending action frame
1273 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001274 if(NULL == cfgState->remain_on_chan_ctx)
1275 {
1276 goto err_rem_channel;
1277 }
1278 }
1279 send_frame:
1280#endif
1281
Jeff Johnsone7245742012-09-05 17:12:55 -07001282 if(!noack)
1283 {
1284 cfgState->buf = vos_mem_malloc( len ); //buf;
1285 if( cfgState->buf == NULL )
1286 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001287
Jeff Johnsone7245742012-09-05 17:12:55 -07001288 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001289
Jeff Johnsone7245742012-09-05 17:12:55 -07001290 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001291
1292#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001293 if( cfgState->remain_on_chan_ctx )
1294 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301295 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07001296 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1297 *cookie = cfgState->action_cookie;
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301298 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07001299 }
1300 else
1301 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001302#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001303 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001304 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001305#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001306 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001307#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301308 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001309
1310 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001311 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1312 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001313 )
1314 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001315 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001316
Jeff Johnsone7245742012-09-05 17:12:55 -07001317 if ((type == SIR_MAC_MGMT_FRAME) &&
1318 (subType == SIR_MAC_MGMT_ACTION) &&
1319 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001320 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001321 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301322 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001323 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001324 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001325 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301326 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001327 }
1328 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1329 {
1330 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301331 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001332 }
1333 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301334
Jeff Johnson295189b2012-06-20 16:38:30 -07001335 if (eHAL_STATUS_SUCCESS !=
1336 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301337 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001338 {
1339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1340 "%s: sme_sendAction returned fail", __func__);
1341 goto err;
1342 }
1343 }
1344 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1345 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1346 )
1347 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001348 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001349 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001350 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001351 {
1352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1353 "%s: WLANSAP_SendAction returned fail", __func__);
1354 goto err;
1355 }
1356 }
1357
1358 return 0;
1359err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001360 if(!noack)
1361 {
1362 hdd_sendActionCnf( pAdapter, FALSE );
1363 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001364 return 0;
1365err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001366 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001367 cfg80211_mgmt_tx_status(
1368#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1369 pAdapter->dev->ieee80211_ptr,
1370#else
1371 pAdapter->dev,
1372#endif
1373 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001374 return 0;
1375}
1376
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301377#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1378int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
1379 struct ieee80211_channel *chan, bool offchan,
1380#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1381 enum nl80211_channel_type channel_type,
1382 bool channel_type_valid,
1383#endif
1384 unsigned int wait,
1385 const u8 *buf, size_t len, bool no_cck,
1386 bool dont_wait_for_ack, u64 *cookie )
1387#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1388int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1389 struct ieee80211_channel *chan, bool offchan,
1390 enum nl80211_channel_type channel_type,
1391 bool channel_type_valid, unsigned int wait,
1392 const u8 *buf, size_t len, bool no_cck,
1393 bool dont_wait_for_ack, u64 *cookie )
1394#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1395int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1396 struct ieee80211_channel *chan, bool offchan,
1397 enum nl80211_channel_type channel_type,
1398 bool channel_type_valid, unsigned int wait,
1399 const u8 *buf, size_t len, u64 *cookie )
1400#else
1401int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1402 struct ieee80211_channel *chan,
1403 enum nl80211_channel_type channel_type,
1404 bool channel_type_valid,
1405 const u8 *buf, size_t len, u64 *cookie )
1406#endif //LINUX_VERSION_CODE
1407{
1408 int ret;
1409
1410 vos_ssr_protect(__func__);
1411#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1412 ret = __wlan_hdd_mgmt_tx(wiphy, wdev,
1413 chan, offchan,
1414#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1415 channel_type,
1416 channel_type_valid,
1417#endif
1418 wait,
1419 buf, len, no_cck,
1420 dont_wait_for_ack, cookie);
1421#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1422 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1423 channel_type, channel_type_valid, wait,
1424 buf, len, no_cck,
1425 dont_wait_for_ack, cookie);
1426#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1427 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1428 channel_type, channel_type_valid, wait,
1429 buf, len, cookie);
1430#else
1431 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, channel_type,
1432 channel_type_valid, buf, len, cookie);
1433#endif //LINUX_VERSION_CODE
1434 vos_ssr_unprotect(__func__);
1435
1436 return ret;
1437}
1438
Jeff Johnson295189b2012-06-20 16:38:30 -07001439#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001440#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301441int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001442 struct wireless_dev *wdev,
1443 u64 cookie)
1444{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301445 u64 cookie_dummy;
1446 cookie_dummy = cookie << 32;
1447 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1448 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001449 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1450}
1451#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301452int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001453 struct net_device *dev,
1454 u64 cookie)
1455{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301456 u64 cookie_dummy;
1457 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1458 cookie_dummy = cookie << 32;
1459 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1460 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1461 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001462 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1463}
1464#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001465#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001466
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301467#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1468#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1469int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1470 struct wireless_dev *wdev,
1471 u64 cookie)
1472{
1473 int ret;
1474
1475 vos_ssr_protect(__func__);
1476 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1477 vos_ssr_unprotect(__func__);
1478
1479 return ret;
1480}
1481#else
1482int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1483 struct net_device *dev,
1484 u64 cookie)
1485{
1486 int ret;
1487
1488 vos_ssr_protect(__func__);
1489 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie);
1490 vos_ssr_unprotect(__func__);
1491
1492 return ret;
1493}
1494#endif
1495#endif
1496
Jeff Johnson295189b2012-06-20 16:38:30 -07001497void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1498{
1499 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1500
Jeff Johnsone7245742012-09-05 17:12:55 -07001501 cfgState->actionFrmState = HDD_IDLE;
1502
Jeff Johnson295189b2012-06-20 16:38:30 -07001503 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1504 if( NULL == cfgState->buf )
1505 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001506 return;
1507 }
1508
1509 /* If skb is NULL it means this packet was received on CFG80211 interface
1510 * else it was received on Monitor interface */
1511 if( cfgState->skb == NULL )
1512 {
1513 /*
1514 * buf is the same pointer it passed us to send. Since we are sending
1515 * it through control path, we use different buffers.
1516 * In case of mac80211, they just push it to the skb and pass the same
1517 * data while sending tx ack status.
1518 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001519 cfg80211_mgmt_tx_status(
1520#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1521 pAdapter->dev->ieee80211_ptr,
1522#else
1523 pAdapter->dev,
1524#endif
1525 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001526 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1527 vos_mem_free( cfgState->buf );
1528 cfgState->buf = NULL;
1529 }
1530 else
1531 {
1532 hdd_adapter_t* pMonAdapter =
1533 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1534 if( pMonAdapter == NULL )
1535 {
1536 hddLog( LOGE, "Not able to get Monitor Adapter");
1537 cfgState->skb = NULL;
1538 vos_mem_free( cfgState->buf );
1539 cfgState->buf = NULL;
1540 complete(&pAdapter->tx_action_cnf_event);
1541 return;
1542 }
1543 /* Send TX completion feedback over monitor interface. */
1544 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1545 cfgState->skb = NULL;
1546 vos_mem_free( cfgState->buf );
1547 cfgState->buf = NULL;
1548 /* Look for the next Mgmt packet to TX */
1549 hdd_mon_tx_mgmt_pkt(pAdapter);
1550 }
1551 complete(&pAdapter->tx_action_cnf_event);
1552}
1553
1554/**
1555 * hdd_setP2pNoa
1556 *
1557 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301558 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001559 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1560 *
1561 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301562 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 *
1564 *ASSUMPTIONS:
1565 *
1566 *
1567 *NOTE:
1568 *
1569 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301570 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001571 *
1572 * @return Status
1573 */
1574
1575int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1576{
1577 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1578 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1579 VOS_STATUS status = VOS_STATUS_SUCCESS;
1580 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001581 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001582 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001583 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001584
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001585 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001586 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301587 {
1588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1589 "%s: strnchr failed to find delimeter",__func__);
1590 return -EINVAL;
1591 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001593 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1594 if (ret < 3)
1595 {
1596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1597 "%s: P2P_SET GO NoA: fail to read param "
1598 "count=%d duration=%d interval=%d \n",
1599 __func__, count, start_time, duration);
1600 return -EINVAL;
1601 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001603 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001604 __func__, count, start_time, duration);
1605 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001606 /* PS Selection
1607 * Periodic NoA (2)
1608 * Single NOA (4)
1609 */
1610 NoA.opp_ps = 0;
1611 NoA.ctWindow = 0;
1612 if (count == 1)
1613 {
1614 NoA.duration = 0;
1615 NoA.single_noa_duration = duration;
1616 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1617 }
1618 else
1619 {
1620 NoA.duration = duration;
1621 NoA.single_noa_duration = 0;
1622 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1623 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001624 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001625 NoA.count = count;
1626 NoA.sessionid = pAdapter->sessionId;
1627
1628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1629 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1630 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001631 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001632 NoA.ctWindow, NoA.duration, NoA.interval,
1633 NoA.count, NoA.single_noa_duration,
1634 NoA.psSelection);
1635
1636 sme_p2pSetPs(hHal, &NoA);
1637 return status;
1638}
1639
1640/**
1641 * hdd_setP2pOpps
1642 *
1643 *FUNCTION:
1644 * This function is called from hdd_hostapd_ioctl function when Driver
1645 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1646 *
1647 *LOGIC:
1648 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1649 *
1650 *ASSUMPTIONS:
1651 *
1652 *
1653 *NOTE:
1654 *
1655 * @param dev Pointer to net device structure
1656 * @param command Pointer to command
1657 *
1658 * @return Status
1659 */
1660
1661int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1662{
1663 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1664 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1665 VOS_STATUS status = VOS_STATUS_SUCCESS;
1666 tP2pPsConfig NoA;
1667 char *param;
1668 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001669 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001670
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001671 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001672 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301673 {
1674 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1675 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001676 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301677 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001678 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001679 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1680 if (ret < 3)
1681 {
1682 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1683 "%s: P2P_SET GO PS: fail to read param "
1684 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1685 __func__, legacy_ps, opp_ps, ctwindow);
1686 return -EINVAL;
1687 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001688 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001689 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001690 __func__, legacy_ps, opp_ps, ctwindow);
1691
1692 /* PS Selection
1693 * Opportunistic Power Save (1)
1694 */
1695
1696 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1697 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301698 * values are coming from wpa_supplicant as -1.
1699 * Example : User want to set ctWindow with 30 then wpa_cli command :
1700 * P2P_SET ctwindow 30
1701 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001702 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301703 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 if (ctwindow != -1)
1705 {
1706
1707 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001708 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001709 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1710
1711 if (ctwindow != pAdapter->ctw)
1712 {
1713 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301714
Jeff Johnson295189b2012-06-20 16:38:30 -07001715 if(pAdapter->ops)
1716 {
1717 NoA.opp_ps = pAdapter->ops;
1718 NoA.ctWindow = pAdapter->ctw;
1719 NoA.duration = 0;
1720 NoA.single_noa_duration = 0;
1721 NoA.interval = 0;
1722 NoA.count = 0;
1723 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1724 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301725
Jeff Johnson295189b2012-06-20 16:38:30 -07001726 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1727 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1728 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001729 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001730 NoA.ctWindow, NoA.duration, NoA.interval,
1731 NoA.count, NoA.single_noa_duration,
1732 NoA.psSelection);
1733
1734 sme_p2pSetPs(hHal, &NoA);
1735 }
1736 return 0;
1737 }
1738 }
1739
1740 if (opp_ps != -1)
1741 {
1742 pAdapter->ops = opp_ps;
1743
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301744 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001745 {
1746 NoA.opp_ps = opp_ps;
1747 NoA.ctWindow = pAdapter->ctw;
1748 NoA.duration = 0;
1749 NoA.single_noa_duration = 0;
1750 NoA.interval = 0;
1751 NoA.count = 0;
1752 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1753 NoA.sessionid = pAdapter->sessionId;
1754
1755 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1756 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1757 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001758 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001759 NoA.ctWindow, NoA.duration, NoA.interval,
1760 NoA.count, NoA.single_noa_duration,
1761 NoA.psSelection);
1762
1763 sme_p2pSetPs(hHal, &NoA);
1764 }
1765 }
1766 return status;
1767}
1768
1769int hdd_setP2pPs( struct net_device *dev, void *msgData )
1770{
1771 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1772 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1773 VOS_STATUS status = VOS_STATUS_SUCCESS;
1774 tP2pPsConfig NoA;
1775 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1776
1777 NoA.opp_ps = pappNoA->opp_ps;
1778 NoA.ctWindow = pappNoA->ctWindow;
1779 NoA.duration = pappNoA->duration;
1780 NoA.interval = pappNoA->interval;
1781 NoA.count = pappNoA->count;
1782 NoA.single_noa_duration = pappNoA->single_noa_duration;
1783 NoA.psSelection = pappNoA->psSelection;
1784 NoA.sessionid = pAdapter->sessionId;
1785
1786 sme_p2pSetPs(hHal, &NoA);
1787 return status;
1788}
Jeff Johnson295189b2012-06-20 16:38:30 -07001789
1790static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1791{
1792 tANI_U8 sessionType;
1793
1794 switch( type )
1795 {
1796 case NL80211_IFTYPE_AP:
1797 sessionType = WLAN_HDD_SOFTAP;
1798 break;
1799 case NL80211_IFTYPE_P2P_GO:
1800 sessionType = WLAN_HDD_P2P_GO;
1801 break;
1802 case NL80211_IFTYPE_P2P_CLIENT:
1803 sessionType = WLAN_HDD_P2P_CLIENT;
1804 break;
1805 case NL80211_IFTYPE_STATION:
1806 sessionType = WLAN_HDD_INFRA_STATION;
1807 break;
1808 case NL80211_IFTYPE_MONITOR:
1809 sessionType = WLAN_HDD_MONITOR;
1810 break;
1811 default:
1812 sessionType = WLAN_HDD_INFRA_STATION;
1813 break;
1814 }
1815
1816 return sessionType;
1817}
1818
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001819#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301820struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001821 struct wiphy *wiphy, const char *name,
1822 enum nl80211_iftype type,
1823 u32 *flags, struct vif_params *params )
1824#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301825struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001826 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1827 u32 *flags, struct vif_params *params )
1828#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301829struct net_device* __wlan_hdd_add_virtual_intf(
Jeff Johnson295189b2012-06-20 16:38:30 -07001830 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1831 u32 *flags, struct vif_params *params )
1832#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301833int __wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
Jeff Johnson295189b2012-06-20 16:38:30 -07001834 enum nl80211_iftype type,
1835 u32 *flags, struct vif_params *params )
1836#endif
1837{
1838 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301839 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301840 hdd_scaninfo_t *pScanInfo = NULL;
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05301841 int ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001842 ENTER();
1843
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05301844 ret = wlan_hdd_validate_context(pHddCtx);
1845 if (0 != ret)
1846 {
1847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1848 "%s: HDD context is not valid", __func__);
1849#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1850 return ERR_PTR(-EINVAL);
1851#else
1852 return -EAGAIN;
1853#endif
1854 }
1855
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301856 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1857 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301858 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1859 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1860 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001861 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001862 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001863 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05301864#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1865 return ERR_PTR(-EINVAL);
1866#else
1867 return -EAGAIN;
1868#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001869 }
1870
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301871 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1872 pScanInfo = &pHddCtx->scan_info;
1873 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1874 (pHddCtx->scan_info.mScanPending))
1875 {
1876 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1877 eCSR_SCAN_ABORT_DEFAULT);
1878 hddLog(VOS_TRACE_LEVEL_INFO,
1879 "%s: Abort Scan while adding virtual interface",__func__);
1880 }
1881
1882 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05301883 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1884 ((NL80211_IFTYPE_P2P_GO == type) ||
1885 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001886 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001887 /* Generate the P2P Interface Address. this address must be
1888 * different from the P2P Device Address.
1889 */
1890 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1891 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301892 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001893 wlan_hdd_get_session_type(type),
1894 name, p2pDeviceAddress.bytes,
1895 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001896 }
1897 else
1898 {
1899 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1900 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1901 }
1902
1903 if( NULL == pAdapter)
1904 {
1905 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1906#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301907 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001908#else
1909 return -EINVAL;
1910#endif
1911 }
1912 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001913#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1914 return pAdapter->dev->ieee80211_ptr;
1915#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001916 return pAdapter->dev;
1917#else
1918 return 0;
1919#endif
1920}
1921
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301922#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1923struct wireless_dev* wlan_hdd_add_virtual_intf(
1924 struct wiphy *wiphy, const char *name,
1925 enum nl80211_iftype type,
1926 u32 *flags, struct vif_params *params )
1927#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1928struct wireless_dev* wlan_hdd_add_virtual_intf(
1929 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1930 u32 *flags, struct vif_params *params )
1931#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1932struct net_device* wlan_hdd_add_virtual_intf(
1933 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1934 u32 *flags, struct vif_params *params )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001935#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301936int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1937 enum nl80211_iftype type,
1938 u32 *flags, struct vif_params *params )
1939#endif
1940{
1941#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)))
1942 struct wireless_dev* wdev;
1943#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1944 struct net_device* ndev;
1945#else
1946 int ret;
1947#endif
1948 vos_ssr_protect(__func__);
1949#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1950 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1951 vos_ssr_unprotect(__func__);
1952 return wdev;
1953#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1954 ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1955 vos_ssr_unprotect(__func__);
1956 return ndev;
1957#else
1958 ret = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1959 vos_ssr_unprotect(__func__);
1960 return ret;
1961#endif
1962}
1963
1964#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1965int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1966#else
1967int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001968#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001969{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001970#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1971 struct net_device *dev = wdev->netdev;
1972#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301973 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301974 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301975 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1976 int status;
1977 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001978
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301979 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1980 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1981 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301982 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1983 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001984
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301985 status = wlan_hdd_validate_context(pHddCtx);
1986
1987 if (0 != status)
1988 {
1989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1990 "%s: HDD context is not valid", __func__);
1991 return status;
1992 }
1993
1994 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001995 pVirtAdapter->macAddressCurrent.bytes );
1996
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05301997 hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301998 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1999 EXIT();
2000 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002001}
2002
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302003#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2004int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
2005#else
2006int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
2007#endif
2008{
2009 int ret;
2010
2011 vos_ssr_protect(__func__);
2012#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2013 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
2014#else
2015 ret = __wlan_hdd_del_virtual_intf(wiphy, dev);
2016#endif
2017 vos_ssr_unprotect(__func__);
2018
2019 return ret;
2020}
2021
Jeff Johnson295189b2012-06-20 16:38:30 -07002022void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002023 tANI_U32 nFrameLength,
2024 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302025 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07002026{
2027 //Indicate a Frame over Monitor Intf.
2028 int rxstat;
2029 struct sk_buff *skb = NULL;
2030 int needed_headroom = 0;
2031 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
2032 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002033#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002034#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2035 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
2036#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002037#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002038 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
2039
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002040 if (NULL == pbFrames)
2041 {
2042 hddLog(LOGE, FL("NULL frame pointer"));
2043 return;
2044 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002045
2046 /* room for the radiotap header based on driver features
2047 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
2048 * RX flags.
2049 * */
2050 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
2051
2052 //alloc skb here
2053 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
2054 if (unlikely(NULL == skb))
2055 {
2056 hddLog( LOGW, FL("Unable to allocate skb"));
2057 return;
2058 }
2059 skb_reserve(skb, VPKT_SIZE_BUFFER);
2060 if (unlikely(skb_headroom(skb) < nFrameLength))
2061 {
2062 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2063 "HDD [%d]: Insufficient headroom, "
2064 "head[%p], data[%p], req[%d]",
2065 __LINE__, skb->head, skb->data, nFrameLength);
2066 kfree_skb(skb);
2067 return ;
2068 }
2069 // actually push the data
2070 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
2071 /* prepend radiotap information */
2072 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
2073 {
2074 hddLog( LOGE, FL("Not Able Add Radio Tap"));
2075 //free skb
2076 kfree_skb(skb);
2077 return ;
2078 }
2079
2080 skb_reset_mac_header( skb );
2081 skb->dev = pMonAdapter->dev;
2082 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002083 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002084#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002085#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002086 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002087#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002088#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002089 rxstat = netif_rx_ni(skb);
2090 if( NET_RX_SUCCESS == rxstat )
2091 {
2092 hddLog( LOG1, FL("Success"));
2093 }
2094 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302095 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07002096
2097 return ;
2098}
2099
2100void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302101 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07002102 tANI_U8* pbFrames,
2103 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05302104 tANI_U32 rxChan,
2105 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07002106{
2107 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302108 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07002109 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002110 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07002111 tActionFrmType actionFrmType;
2112 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302113 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05302114 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302115 VOS_STATUS status;
2116 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002117
Arif Hussain6d2a3322013-11-17 19:50:10 -08002118 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002119 __func__, frameType, nFrameLength);
2120
2121 if (NULL == pAdapter)
2122 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002123 hddLog(LOGE, FL("pAdapter is NULL"));
2124 return;
2125 }
2126
2127 if (0 == nFrameLength)
2128 {
2129 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2130 return;
2131 }
2132
2133 if (NULL == pbFrames)
2134 {
2135 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002136 return;
2137 }
2138
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002139 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2140 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2141
2142 /* Get pAdapter from Destination mac address of the frame */
2143 if ((type == SIR_MAC_MGMT_FRAME) &&
2144 (subType != SIR_MAC_MGMT_PROBE_REQ))
2145 {
2146 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
2147 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
2148 if (NULL == pAdapter)
2149 {
2150 /* Under assumtion that we don't receive any action frame
2151 * with BCST as destination we dropping action frame
2152 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08002153 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
2154 MAC_ADDRESS_STR ,
2155 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
2156 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08002157 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002158 return;
2159 }
2160 }
2161
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002162
Jeff Johnson295189b2012-06-20 16:38:30 -07002163 if (NULL == pAdapter->dev)
2164 {
2165 hddLog( LOGE, FL("pAdapter->dev is NULL"));
2166 return;
2167 }
2168
2169 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2170 {
2171 hddLog( LOGE, FL("pAdapter has invalid magic"));
2172 return;
2173 }
2174
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302175 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2176 if (NULL == pHddCtx)
2177 {
2178 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
2179 return;
2180 }
2181
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002182 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2183 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07002184 {
2185 hdd_adapter_t *pMonAdapter =
2186 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
2187
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002188 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07002189 {
2190 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
2191 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
2192 pbFrames, frameType);
2193 return;
2194 }
2195 }
2196
2197 //Channel indicated may be wrong. TODO
2198 //Indicate an action frame.
2199 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
2200 {
2201 freq = ieee80211_channel_to_frequency( rxChan,
2202 IEEE80211_BAND_2GHZ);
2203 }
2204 else
2205 {
2206 freq = ieee80211_channel_to_frequency( rxChan,
2207 IEEE80211_BAND_5GHZ);
2208 }
2209
Jeff Johnsone7245742012-09-05 17:12:55 -07002210 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302211 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302212
2213 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002214 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07002215 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002216 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
2217 {
2218 // public action frame
2219 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08002220 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 -08002221 // P2P action frames
2222 {
2223 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002224 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002225#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002226 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
2227 {
2228 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
2229 actionFrmType);
2230 }
2231 else
2232 {
2233 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
2234 p2p_action_frame_type[actionFrmType]);
2235 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
2236 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2237 {
2238 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
2239 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002240 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002241 }
2242 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
2243 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
2244 {
2245 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08002246 hddLog(LOGE,"[P2P State]GO negotiation progress to "
2247 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002248 }
2249 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
2250 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2251 {
2252 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
2253 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
2254 " completed state Autonomous GO formation");
2255 }
2256 }
2257#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302258 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
2259 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
2260 {
2261 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
2262 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
2263 actionFrmType == WLAN_HDD_INVITATION_REQ ||
2264 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
2265 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
2266 {
2267 hddLog( LOG1, "Extend RoC timer on reception of"
2268 " Action Frame");
2269 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
2270 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
2271 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
2272 else
2273 extend_time = ACTION_FRAME_DEFAULT_WAIT;
2274 if (completion_done(&pAdapter->rem_on_chan_ready_event))
2275 {
2276 vos_timer_stop(
2277 &pRemainChanCtx->hdd_remain_on_chan_timer);
2278 status = vos_timer_start(
2279 &pRemainChanCtx->hdd_remain_on_chan_timer,
2280 extend_time);
2281 if (status != VOS_STATUS_SUCCESS)
2282 {
2283 hddLog( LOGE, "ROC timer start failed");
2284 }
2285 }
2286 else
2287 {
2288 // Buffer Packet
2289 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2290 {
2291 pRemainChanCtx->action_pkt_buff.frame_length =
2292 nFrameLength;
2293 pRemainChanCtx->action_pkt_buff.freq = freq;
2294 pRemainChanCtx->action_pkt_buff.frame_ptr
2295 = vos_mem_malloc(nFrameLength);
2296 vos_mem_copy(
2297 pRemainChanCtx->action_pkt_buff.frame_ptr,
2298 pbFrames, nFrameLength);
2299 hddLog( LOGE,"%s:"
2300 "Action Pkt Cached successfully !!!", __func__);
2301 }
2302 else
2303 {
2304 hddLog( LOGE,"%s:"
2305 "Frames are pending. dropping frame !!!",
2306 __func__);
2307 }
2308 return;
2309 }
2310 }
2311 }
2312 if (pRemainChanCtx != NULL &&
2313 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2314 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2315 hddLog( LOG1, "%s:"
2316 "Rcvd action frame after timer expired ", __func__);
2317
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302318 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2319 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2320 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2321 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2322 {
2323 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2324 __func__);
2325 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002326 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002327 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002328#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002329 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 -07002330 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002331 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
2332#ifdef WLAN_FEATURE_TDLS_DEBUG
2333 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2334 MAC_ADDR_ARRAY(mac),rxRssi);
2335#endif
2336 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2337 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002338 }
2339#endif
2340 }
Kaushik, Sushant507a8612014-10-21 17:00:55 +05302341
2342 pScanInfo = &pHddCtx->scan_info;
2343 if ((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2344 {
2345 hddLog(LOGE,"Action frame received when Scanning is in"
2346 " progress. Abort Scan.");
2347 hdd_abort_mac_scan(pAdapter->pHddCtx,
2348 pScanInfo->sessionId,
2349 eCSR_SCAN_ABORT_DEFAULT);
2350 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002351#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002352 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2353 {
2354 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2355 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2356 {
2357 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2358 actionFrmType);
2359 }
2360 else
2361 {
2362 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2363 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002364 }
2365 }
2366#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002367 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2368 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2369 {
Kumar Anand82c009f2014-05-29 00:29:42 -07002370 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
2371 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002372 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002373 }
2374
Jeff Johnson295189b2012-06-20 16:38:30 -07002375 //Indicate Frame Over Normal Interface
2376 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2377
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002378#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2379 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2380 pbFrames, nFrameLength,
2381 GFP_ATOMIC );
2382#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002383 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2384 pbFrames, nFrameLength,
2385 GFP_ATOMIC );
2386#else
2387 cfg80211_rx_mgmt( pAdapter->dev, freq,
2388 pbFrames, nFrameLength,
2389 GFP_ATOMIC );
2390#endif //LINUX_VERSION_CODE
2391}
2392
2393/*
2394 * ieee80211_add_rx_radiotap_header - add radiotap header
2395 */
2396static int hdd_wlan_add_rx_radiotap_hdr (
2397 struct sk_buff *skb, int rtap_len, int flag )
2398{
2399 u8 rtap_temp[20] = {0};
2400 struct ieee80211_radiotap_header *rthdr;
2401 unsigned char *pos;
2402 u16 rx_flags = 0;
2403
2404 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2405
2406 /* radiotap header, set always present flags */
2407 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2408 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2409 rthdr->it_len = cpu_to_le16(rtap_len);
2410
2411 pos = (unsigned char *) (rthdr + 1);
2412
2413 /* the order of the following fields is important */
2414
2415 /* IEEE80211_RADIOTAP_FLAGS */
2416 *pos = 0;
2417 pos++;
2418
2419 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2420 /* ensure 2 byte alignment for the 2 byte field as required */
2421 if ((pos - (u8 *)rthdr) & 1)
2422 pos++;
2423 put_unaligned_le16(rx_flags, pos);
2424 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302425
Jeff Johnson295189b2012-06-20 16:38:30 -07002426 // actually push the data
2427 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2428
2429 return 0;
2430}
2431
2432static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2433 hdd_cfg80211_state_t* cfgState,
2434 tANI_BOOLEAN actionSendSuccess )
2435{
2436 struct ieee80211_radiotap_header *rthdr;
2437 unsigned char *pos;
2438 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002439#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002440#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2441 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2442#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002443#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002444
2445 /* 2 Byte for TX flags and 1 Byte for Retry count */
2446 u32 rtHdrLen = sizeof(*rthdr) + 3;
2447
2448 u8 *data;
2449
2450 /* We have to return skb with Data starting with MAC header. We have
2451 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2452 * entire skb->len from skb and then we will push cfgState->buf to skb
2453 * */
2454 if( NULL == skb_pull(skb, skb->len) )
2455 {
2456 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2457 kfree_skb(cfgState->skb);
2458 return;
2459 }
2460
2461 data = skb_push( skb, cfgState->len );
2462
2463 if (data == NULL)
2464 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002465 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002466 kfree_skb( cfgState->skb );
2467 return;
2468 }
2469
2470 memcpy( data, cfgState->buf, cfgState->len );
2471
2472 /* send frame to monitor interfaces now */
2473 if( skb_headroom(skb) < rtHdrLen )
2474 {
2475 hddLog( LOGE, FL("No headroom for rtap header"));
2476 kfree_skb(cfgState->skb);
2477 return;
2478 }
2479
2480 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2481
2482 memset( rthdr, 0, rtHdrLen );
2483 rthdr->it_len = cpu_to_le16( rtHdrLen );
2484 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2485 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2486 );
2487
2488 pos = (unsigned char *)( rthdr+1 );
2489
2490 // Fill TX flags
2491 *pos = actionSendSuccess;
2492 pos += 2;
2493
2494 // Fill retry count
2495 *pos = 0;
2496 pos++;
2497
2498 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002499 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002500 skb->pkt_type = PACKET_OTHERHOST;
2501 skb->protocol = htons(ETH_P_802_2);
2502 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002503#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002504#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002505 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002506#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002507#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002508 if (in_interrupt())
2509 netif_rx( skb );
2510 else
2511 netif_rx_ni( skb );
2512
2513 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05302514 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302515 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002516
2517}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302518
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05302519void hdd_p2p_roc_work_queue(struct work_struct *work)
2520{
2521 hdd_adapter_t *pAdapter = container_of(to_delayed_work(work), hdd_adapter_t, roc_work);
2522 hddLog( VOS_TRACE_LEVEL_INFO, FL("%s: "), __func__);
2523 wlan_hdd_p2p_start_remain_on_channel(pAdapter);
2524 return;
2525}
2526