blob: ed2279f4c1b189c261605f8f8a313244375f1da0 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**========================================================================
29
30 \file wlan_hdd_p2p.c
31
32 \brief WLAN Host Device Driver implementation for P2P commands interface
33
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 );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530563 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530564 VOS_STATUS checkReadyInd;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530565 hdd_adapter_t *pStaAdapter;
566
Jeff Johnson32d95a32012-09-10 13:15:23 -0700567 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
568 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700569#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530570 hddLog(VOS_TRACE_LEVEL_INFO,
571 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
572 " request type %d, cookie %llu",
573 chan->hw_value, chan->center_freq, channel_type, duration,
574 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700575#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530576 hddLog(VOS_TRACE_LEVEL_INFO,
577 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
578 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
579 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700580#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700581 //Cancel existing remain On Channel if any
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530582 checkReadyInd = wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
583 if (VOS_STATUS_SUCCESS != checkReadyInd)
584 {
585 hddLog( LOGE, FL("Cancel Roc in progress"));
586 return -EBUSY;
587 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700588
Jeff Johnsone7245742012-09-05 17:12:55 -0700589 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700590 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700591 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700592 * channel requets when Load/Unload is in progress*/
Rashmi Ramannab1429032014-04-26 14:59:09 +0530593 if (WLAN_HDD_IS_LOAD_UNLOAD_IN_PROGRESS(((hdd_context_t *)pAdapter->pHddCtx))
Padma, Santhosh Kumar98f271d2014-12-31 17:23:31 +0530594 || hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx))
Jeff Johnson295189b2012-06-20 16:38:30 -0700595 {
596 hddLog( LOGE,
Rashmi Ramannab1429032014-04-26 14:59:09 +0530597 "%s: Wlan Load/Unload or Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700598 return -EBUSY;
599 }
600
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700601 if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
602 {
603 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
604 "%s:LOGP in Progress. Ignore!!!", __func__);
605 return -EAGAIN;
606 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700607 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
608 if( NULL == pRemainChanCtx )
609 {
610 hddLog(VOS_TRACE_LEVEL_FATAL,
611 "%s: Not able to allocate memory for Channel context",
612 __func__);
613 return -ENOMEM;
614 }
615
616 vos_mem_copy( &pRemainChanCtx->chan, chan,
617 sizeof(struct ieee80211_channel) );
618
Yue Maf49ba872013-08-19 12:04:25 -0700619#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700620 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700621#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700622 pRemainChanCtx->duration = duration;
623 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800624 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700625 pRemainChanCtx->cookie = *cookie;
626 pRemainChanCtx->rem_on_chan_request = request_type;
627 cfgState->remain_on_chan_ctx = pRemainChanCtx;
628 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530629 pRemainChanCtx->action_pkt_buff.freq = 0;
630 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
631 pRemainChanCtx->action_pkt_buff.frame_length = 0;
632 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530633 pRemainChanCtx->is_pending_roc_cancelled = FALSE;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530634
Jeff Johnson295189b2012-06-20 16:38:30 -0700635 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
636
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530637 if (REMAIN_ON_CHANNEL_REQUEST == request_type)
Jeff Johnson295189b2012-06-20 16:38:30 -0700638 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530639 pStaAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
640 if((NULL != pStaAdapter)&&
641 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pStaAdapter)))
Sushant Kaushik298a8592014-12-09 17:34:07 +0530642 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530643 if (pAdapter->lastRocTs !=0 &&
644 ((vos_timer_get_system_time() - pAdapter->lastRocTs )
645 < pHddCtx->cfg_ini->gP2PListenDeferInterval))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530646 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530647 if (pRemainChanCtx->duration > HDD_P2P_MAX_ROC_DURATION)
648 pRemainChanCtx->duration = HDD_P2P_MAX_ROC_DURATION;
649 schedule_delayed_work(&pAdapter->roc_work,
650 msecs_to_jiffies(pHddCtx->cfg_ini->gP2PListenDeferInterval));
651 hddLog(VOS_TRACE_LEVEL_INFO, "Defer interval is %hu, pAdapter %p",
652 pHddCtx->cfg_ini->gP2PListenDeferInterval, pAdapter);
653 return 0;
Rashmi Ramannac7744532013-10-06 16:49:08 +0530654 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800655 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700656 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530657
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530658 return wlan_hdd_p2p_start_remain_on_channel(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700659}
660
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530661int __wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800662#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
663 struct wireless_dev *wdev,
664#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700665 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800666#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700667 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700668#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700669 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700670#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700671 unsigned int duration, u64 *cookie )
672{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800673#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
674 struct net_device *dev = wdev->netdev;
675#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530676 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
677
678 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
679 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
680 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Jeff Johnson295189b2012-06-20 16:38:30 -0700681 return wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700682 chan,
683#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
684 channel_type,
685#endif
686 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700687 REMAIN_ON_CHANNEL_REQUEST);
688}
689
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530690int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
691#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
692 struct wireless_dev *wdev,
693#else
694 struct net_device *dev,
695#endif
696 struct ieee80211_channel *chan,
697#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
698 enum nl80211_channel_type channel_type,
699#endif
700 unsigned int duration, u64 *cookie )
701{
702 int ret;
703
704 vos_ssr_protect(__func__);
705 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
706#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
707 wdev,
708#else
709 dev,
710#endif
711 chan,
712#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
713 channel_type,
714#endif
715 duration, cookie);
716 vos_ssr_unprotect(__func__);
717
718 return ret;
719}
720
721
Jeff Johnson295189b2012-06-20 16:38:30 -0700722void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
723{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530724 hdd_cfg80211_state_t *cfgState = NULL;
725 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530726 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530727 if (NULL == pAdapter)
728 {
729 hddLog(LOGE, FL("pAdapter is NULL"));
730 return;
731 }
732 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
733 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530734 hddLog( LOG1, "Ready on chan ind");
Jeff Johnson295189b2012-06-20 16:38:30 -0700735 if( pRemainChanCtx != NULL )
736 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530737 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
738 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
739 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530740 //start timer for actual duration
741 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
742 (pRemainChanCtx->duration));
743 if (VOS_STATUS_SUCCESS!=status)
744 {
745 hddLog( LOGE, FL("Remain on Channel timer start failed"));
746 }
747 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700748 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800749 cfg80211_ready_on_channel(
750#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
751 pAdapter->dev->ieee80211_ptr,
752#else
753 pAdapter->dev,
754#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800755 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700756 &pRemainChanCtx->chan,
757#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
758 pRemainChanCtx->chan_type,
759#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700760 pRemainChanCtx->duration, GFP_KERNEL );
761 }
762#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530763 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700764 {
765 complete(&pAdapter->offchannel_tx_event);
766 }
767#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530768 // Check for cached action frame
769 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
770 {
771#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
772 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
773 pRemainChanCtx->action_pkt_buff.freq, 0,
774 pRemainChanCtx->action_pkt_buff.frame_ptr,
775 pRemainChanCtx->action_pkt_buff.frame_length,
776 GFP_ATOMIC );
777#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
778 cfg80211_rx_mgmt( pAdapter->dev,
779 pRemainChanCtx->action_pkt_buff.freq, 0,
780 pRemainChanCtx->action_pkt_buff.frame_ptr,
781 pRemainChanCtx->action_pkt_buff.frame_length,
782 GFP_ATOMIC );
783#else
784 cfg80211_rx_mgmt( pAdapter->dev,
785 pRemainChanCtx->action_pkt_buff.freq,
786 pRemainChanCtx->action_pkt_buff.frame_ptr,
787 pRemainChanCtx->action_pkt_buff.frame_length,
788 GFP_ATOMIC );
789#endif //LINUX_VERSION_CODE
790 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
791 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
792 pRemainChanCtx->action_pkt_buff.frame_length = 0;
793 pRemainChanCtx->action_pkt_buff.freq = 0;
794 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
795 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530796 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
797 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700798 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530799 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
800 {
801 /* since pRemainChanCtx->is_pending_roc_cancelled is
802 * set, it means Cancel Reamain on channel command is
803 * pending because remain on channel event was not
804 * ready when cancel ROC was issued.So issue
805 * cancel ROC now.
806 */
807 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
808 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700809 }
810 else
811 {
812 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
813 }
814 return;
815}
816
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530817int __wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800818#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
819 struct wireless_dev *wdev,
820#else
821 struct net_device *dev,
822#endif
823 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700824{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800825#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
826 struct net_device *dev = wdev->netdev;
827#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700828 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700829 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530830 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530831 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
832 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530833 u64 cookie_dummy;
834 cookie_dummy = cookie << 32;
835 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
836 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
837 pAdapter->sessionId, cookie_dummy));
838 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -0700839
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530840 status = wlan_hdd_validate_context(pHddCtx);
841
842 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700843 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
845 "%s: HDD context is not valid", __func__);
846 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700847 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530848 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
849
Jeff Johnson295189b2012-06-20 16:38:30 -0700850 /* FIXME cancel currently running remain on chan.
851 * Need to check cookie and cancel accordingly
852 */
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530853 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700854 if( (cfgState->remain_on_chan_ctx == NULL) ||
855 (cfgState->remain_on_chan_ctx->cookie != cookie) )
856 {
857 hddLog( LOGE,
858 "%s: No Remain on channel pending with specified cookie value",
859 __func__);
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530860 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700861 return -EINVAL;
862 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530863 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
864 {
865 /* wait until remain on channel ready event received
866 * for already issued remain on channel request */
867 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
868 msecs_to_jiffies(WAIT_REM_CHAN_READY));
869 if (0 >= status)
870 {
871 hddLog( LOGE,
872 "%s: timeout waiting for remain on channel ready indication %d",
873 __func__, status);
874 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530875 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530876 return 0;
877
878 }
879 }
880 else
881 {
882 hddLog( LOG1, FL("Cancel ROC event is already pending, "
883 "waiting for ready on channel indication.") );
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530884 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530885 return 0;
886 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530887 if (NULL != cfgState->remain_on_chan_ctx)
888 {
889 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
890 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
891 {
892 hddLog( LOG1,
893 FL("ROC timer cancellation in progress,"
894 " wait for completion"));
895 status = wait_for_completion_interruptible_timeout(
896 &pAdapter->cancel_rem_on_chan_var,
897 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
898 if (0 >= status)
899 {
900 hddLog( LOGE,
901 "%s:wait on cancel_rem_on_chan_var failed %d",
902 __func__, status);
903 }
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530904 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530905 return 0;
906 }
907 else
908 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
909 }
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530910 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700911 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
912 /* Issue abort remain on chan request to sme.
913 * The remain on channel callback will make sure the remain_on_chan
914 * expired event is sent.
915 */
916 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700917 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
918 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700919 )
920 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530921 tANI_U8 sessionId = pAdapter->sessionId;
Jeff Johnson295189b2012-06-20 16:38:30 -0700922 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
923 sessionId );
924 }
925 else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
926 (WLAN_HDD_P2P_GO == pAdapter->device_mode)
927 )
928 {
929 WLANSAP_CancelRemainOnChannel(
930 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
931 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530932 else
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 {
934 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
935 __func__, pAdapter->device_mode);
936 return -EIO;
937 }
c_hpothu7f63e882013-10-02 19:13:35 +0530938 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700939 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +0530940 if (0 >= status)
941 {
942 hddLog( LOGE,
943 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
944 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530945 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -0700946 return 0;
947}
948
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530949int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800950#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530951 struct wireless_dev *wdev,
952#else
953 struct net_device *dev,
954#endif
955 u64 cookie )
956{
957 int ret;
958
959 vos_ssr_protect(__func__);
960 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
961#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
962 wdev,
963#else
964 dev,
965#endif
966 cookie);
967 vos_ssr_unprotect(__func__);
968
969 return ret;
970}
971
972
973#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
974int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800975 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -0700976#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800977 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700978 bool channel_type_valid,
979#endif
980 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800981 const u8 *buf, size_t len, bool no_cck,
982 bool dont_wait_for_ack, u64 *cookie )
983#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530984int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700985 struct ieee80211_channel *chan, bool offchan,
986 enum nl80211_channel_type channel_type,
987 bool channel_type_valid, unsigned int wait,
988 const u8 *buf, size_t len, bool no_cck,
989 bool dont_wait_for_ack, u64 *cookie )
990#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530991int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700992 struct ieee80211_channel *chan, bool offchan,
993 enum nl80211_channel_type channel_type,
994 bool channel_type_valid, unsigned int wait,
995 const u8 *buf, size_t len, u64 *cookie )
996#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530997int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -0700998 struct ieee80211_channel *chan,
999 enum nl80211_channel_type channel_type,
1000 bool channel_type_valid,
1001 const u8 *buf, size_t len, u64 *cookie )
1002#endif //LINUX_VERSION_CODE
1003{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001004#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1005 struct net_device *dev = wdev->netdev;
1006#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001007 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301008 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1009 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
1010 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -07001011 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
1012 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
Mukul Sharma1e5d0b72014-07-01 19:22:21 +05301013 tActionFrmType actionFrmType = WLAN_HDD_ACTION_FRM_TYPE_MAX;
Jeff Johnsone7245742012-09-05 17:12:55 -07001014 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301015 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -07001016
Jeff Johnson295189b2012-06-20 16:38:30 -07001017#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1018 hdd_adapter_t *goAdapter;
1019#endif
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301020
1021 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301022 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
1023 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301024 status = wlan_hdd_validate_context(pHddCtx);
1025
1026 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001027 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1029 "%s: HDD context is not valid", __func__);
1030 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001031 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301032
c_hpothu7f63e882013-10-02 19:13:35 +05301033 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
1034 __func__, pAdapter->device_mode, type);
1035
1036
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001037 if ((type == SIR_MAC_MGMT_FRAME) &&
1038 (subType == SIR_MAC_MGMT_ACTION) &&
1039 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
1040 {
1041 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301042#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001043 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001044 {
1045 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
1046 actionFrmType);
1047 }
1048 else
1049 {
1050 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
1051 p2p_action_frame_type[actionFrmType]);
1052 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1053 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1054 {
1055 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1056 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001057 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001058 }
1059 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1060 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1061 {
1062 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1063 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
1064 " completed state");
1065 }
1066 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001067#endif
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301068 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001069
Jeff Johnsone7245742012-09-05 17:12:55 -07001070#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1071 noack = dont_wait_for_ack;
1072#endif
1073
1074 //If the wait is coming as 0 with off channel set
1075 //then set the wait to 200 ms
1076 if (offchan && !wait)
1077 wait = ACTION_FRAME_DEFAULT_WAIT;
1078
Jeff Johnson295189b2012-06-20 16:38:30 -07001079 //Call sme API to send out a action frame.
1080 // OR can we send it directly through data path??
1081 // After tx completion send tx status back.
1082 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1083 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1084 )
1085 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001086 if (type == SIR_MAC_MGMT_FRAME)
1087 {
1088 if (subType == SIR_MAC_MGMT_PROBE_RSP)
1089 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301090 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -07001091 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301092 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001093 goto err_rem_channel;
1094 }
1095 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
1096 (subType == SIR_MAC_MGMT_DEAUTH))
1097 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001098 /* During EAP failure or P2P Group Remove supplicant
1099 * is sending del_station command to driver. From
1100 * del_station function, Driver will send deauth frame to
1101 * p2p client. No need to send disassoc frame from here.
1102 * so Drop the frame here and send tx indication back to
1103 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -07001104 */
1105 tANI_U8 dstMac[ETH_ALEN] = {0};
1106 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07001107 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -08001109 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001110 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08001111 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001112 goto err_rem_channel;
1113 }
1114 }
1115 }
1116
1117 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001118 {
1119 if ( !noack )
1120 {
1121 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1122 __func__);
1123 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1124 }
1125 else
1126 {
1127 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1128 __func__);
1129 return -EBUSY;
1130 }
1131 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001132
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301133 if( subType == SIR_MAC_MGMT_ACTION)
1134 {
1135 hddLog( LOG1, "Action frame tx request : %s",
1136 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1137 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001138
1139#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1140 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1141
1142 //If GO adapter exists and operating on same frequency
1143 //then we will not request remain on channel
1144 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1145 == goAdapter->sessionCtx.ap.operatingChannel ) )
1146 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301147 /* if GO exist and is not off channel
1148 * wait time should be zero.
1149 */
1150 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001151 goto send_frame;
1152 }
1153#endif
1154
1155#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1156 if( offchan && wait)
1157 {
1158 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301159 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001160 // In case of P2P Client mode if we are already
1161 // on the same channel then send the frame directly
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301162 mutex_lock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301163 if( (cfgState->remain_on_chan_ctx != NULL) &&
1164 (cfgState->current_freq == chan->center_freq)
1165 )
1166 {
1167 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1168 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301169 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301170 /* Some times FW is taking almost 500 msec for
1171 * full 15 retries, which leads to ROC expiration
1172 * by the time peer gets response from other peer.
1173 * Therefore as part of temporary fix , in host
1174 * ROC time is extended. For frames where we are
1175 * expecting response from peer , its extended by
1176 * 500 msec to make ROC wait time as 1 sec and
1177 * in other cases its extended by 300 msec to make
1178 * total ROC wait as 500 msec.
1179 * TODO: FW needs to fix as why 15 retry is taking
1180 * such long time.
1181 */
1182 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1183 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1184 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1185 wait = wait + ACTION_FRAME_RSP_WAIT;
1186 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1187 actionFrmType == WLAN_HDD_INVITATION_RESP )
1188 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301189 vos_timer_stop(
1190 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1191 status = vos_timer_start(
1192 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1193 wait);
1194 if ( status != VOS_STATUS_SUCCESS )
vamsida0e5ab2013-12-26 14:33:27 +05301195 {
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301196 hddLog( LOGE, "Remain on Channel timer start failed");
1197 }
1198
1199 hddLog(VOS_TRACE_LEVEL_INFO,
1200 "action frame: extending the wait time %u",
1201 wait);
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301202 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301203 goto send_frame;
1204 }
1205 else
1206 {
1207 if ( TRUE ==
1208 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1209 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301210 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301211 hddLog(VOS_TRACE_LEVEL_INFO,
1212 "action frame tx: waiting for completion of ROC ");
1213
1214 status = wait_for_completion_interruptible_timeout(
1215 &pAdapter->cancel_rem_on_chan_var,
1216 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1217 if (0 >= status)
1218 {
1219 hddLog( LOGE,
1220 "%s:wait on cancel_rem_on_chan_var failed %d",
1221 __func__, status);
1222 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301223 goto bypass_lock;
vamsida0e5ab2013-12-26 14:33:27 +05301224 }
1225 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301226 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301227 mutex_unlock(&pHddCtx->roc_lock);
1228bypass_lock:
Rashmi Ramannac7744532013-10-06 16:49:08 +05301229 hddLog(VOS_TRACE_LEVEL_INFO,
1230 "action frame: Request ROC for wait time %u", wait);
Jeff Johnson295189b2012-06-20 16:38:30 -07001231 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001232 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001233 chan,
1234#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1235 channel_type,
1236#endif
1237 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301238 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001239
1240 if(0 != status)
1241 {
1242 if( (-EBUSY == status) &&
1243 (cfgState->current_freq == chan->center_freq) )
1244 {
1245 goto send_frame;
1246 }
1247 goto err_rem_channel;
1248 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001249 /* Wait for driver to be ready on the requested channel */
1250 status = wait_for_completion_interruptible_timeout(
1251 &pAdapter->offchannel_tx_event,
1252 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301253 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001254 {
c_hpothu7f63e882013-10-02 19:13:35 +05301255 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001256 goto err_rem_channel;
1257 }
1258 }
1259 else if ( offchan )
1260 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001261 /* Check before sending action frame
1262 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001263 if(NULL == cfgState->remain_on_chan_ctx)
1264 {
1265 goto err_rem_channel;
1266 }
1267 }
1268 send_frame:
1269#endif
1270
Jeff Johnsone7245742012-09-05 17:12:55 -07001271 if(!noack)
1272 {
1273 cfgState->buf = vos_mem_malloc( len ); //buf;
1274 if( cfgState->buf == NULL )
1275 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001276
Jeff Johnsone7245742012-09-05 17:12:55 -07001277 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001278
Jeff Johnsone7245742012-09-05 17:12:55 -07001279 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001280
1281#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001282 if( cfgState->remain_on_chan_ctx )
1283 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301284 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07001285 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1286 *cookie = cfgState->action_cookie;
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301287 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07001288 }
1289 else
1290 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001291#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001292 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001293 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001294#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001295 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001296#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301297 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001298
1299 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001300 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1301 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001302 )
1303 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001304 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001305
Jeff Johnsone7245742012-09-05 17:12:55 -07001306 if ((type == SIR_MAC_MGMT_FRAME) &&
1307 (subType == SIR_MAC_MGMT_ACTION) &&
1308 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001309 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001310 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301311 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001312 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001313 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001314 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301315 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001316 }
1317 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1318 {
1319 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301320 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001321 }
1322 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301323
Jeff Johnson295189b2012-06-20 16:38:30 -07001324 if (eHAL_STATUS_SUCCESS !=
1325 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301326 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001327 {
1328 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1329 "%s: sme_sendAction returned fail", __func__);
1330 goto err;
1331 }
1332 }
1333 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1334 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1335 )
1336 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001337 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001338 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001339 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001340 {
1341 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1342 "%s: WLANSAP_SendAction returned fail", __func__);
1343 goto err;
1344 }
1345 }
1346
1347 return 0;
1348err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001349 if(!noack)
1350 {
1351 hdd_sendActionCnf( pAdapter, FALSE );
1352 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001353 return 0;
1354err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001355 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001356 cfg80211_mgmt_tx_status(
1357#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1358 pAdapter->dev->ieee80211_ptr,
1359#else
1360 pAdapter->dev,
1361#endif
1362 *cookie, buf, len, FALSE, GFP_KERNEL );
Jeff Johnson295189b2012-06-20 16:38:30 -07001363 return 0;
1364}
1365
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301366#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1367int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
1368 struct ieee80211_channel *chan, bool offchan,
1369#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1370 enum nl80211_channel_type channel_type,
1371 bool channel_type_valid,
1372#endif
1373 unsigned int wait,
1374 const u8 *buf, size_t len, bool no_cck,
1375 bool dont_wait_for_ack, u64 *cookie )
1376#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1377int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1378 struct ieee80211_channel *chan, bool offchan,
1379 enum nl80211_channel_type channel_type,
1380 bool channel_type_valid, unsigned int wait,
1381 const u8 *buf, size_t len, bool no_cck,
1382 bool dont_wait_for_ack, u64 *cookie )
1383#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1384int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1385 struct ieee80211_channel *chan, bool offchan,
1386 enum nl80211_channel_type channel_type,
1387 bool channel_type_valid, unsigned int wait,
1388 const u8 *buf, size_t len, u64 *cookie )
1389#else
1390int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1391 struct ieee80211_channel *chan,
1392 enum nl80211_channel_type channel_type,
1393 bool channel_type_valid,
1394 const u8 *buf, size_t len, u64 *cookie )
1395#endif //LINUX_VERSION_CODE
1396{
1397 int ret;
1398
1399 vos_ssr_protect(__func__);
1400#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1401 ret = __wlan_hdd_mgmt_tx(wiphy, wdev,
1402 chan, offchan,
1403#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1404 channel_type,
1405 channel_type_valid,
1406#endif
1407 wait,
1408 buf, len, no_cck,
1409 dont_wait_for_ack, cookie);
1410#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1411 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1412 channel_type, channel_type_valid, wait,
1413 buf, len, no_cck,
1414 dont_wait_for_ack, cookie);
1415#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1416 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1417 channel_type, channel_type_valid, wait,
1418 buf, len, cookie);
1419#else
1420 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, channel_type,
1421 channel_type_valid, buf, len, cookie);
1422#endif //LINUX_VERSION_CODE
1423 vos_ssr_unprotect(__func__);
1424
1425 return ret;
1426}
1427
Jeff Johnson295189b2012-06-20 16:38:30 -07001428#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001429#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301430int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001431 struct wireless_dev *wdev,
1432 u64 cookie)
1433{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301434 u64 cookie_dummy;
1435 cookie_dummy = cookie << 32;
1436 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1437 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001438 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1439}
1440#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301441int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001442 struct net_device *dev,
1443 u64 cookie)
1444{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301445 u64 cookie_dummy;
1446 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1447 cookie_dummy = cookie << 32;
1448 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1449 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1450 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001451 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1452}
1453#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001454#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001455
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301456#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1457#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1458int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1459 struct wireless_dev *wdev,
1460 u64 cookie)
1461{
1462 int ret;
1463
1464 vos_ssr_protect(__func__);
1465 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1466 vos_ssr_unprotect(__func__);
1467
1468 return ret;
1469}
1470#else
1471int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1472 struct net_device *dev,
1473 u64 cookie)
1474{
1475 int ret;
1476
1477 vos_ssr_protect(__func__);
1478 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie);
1479 vos_ssr_unprotect(__func__);
1480
1481 return ret;
1482}
1483#endif
1484#endif
1485
Jeff Johnson295189b2012-06-20 16:38:30 -07001486void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1487{
1488 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1489
Jeff Johnsone7245742012-09-05 17:12:55 -07001490 cfgState->actionFrmState = HDD_IDLE;
1491
Jeff Johnson295189b2012-06-20 16:38:30 -07001492 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1493 if( NULL == cfgState->buf )
1494 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001495 return;
1496 }
1497
1498 /* If skb is NULL it means this packet was received on CFG80211 interface
1499 * else it was received on Monitor interface */
1500 if( cfgState->skb == NULL )
1501 {
1502 /*
1503 * buf is the same pointer it passed us to send. Since we are sending
1504 * it through control path, we use different buffers.
1505 * In case of mac80211, they just push it to the skb and pass the same
1506 * data while sending tx ack status.
1507 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001508 cfg80211_mgmt_tx_status(
1509#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1510 pAdapter->dev->ieee80211_ptr,
1511#else
1512 pAdapter->dev,
1513#endif
1514 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001515 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1516 vos_mem_free( cfgState->buf );
1517 cfgState->buf = NULL;
1518 }
1519 else
1520 {
1521 hdd_adapter_t* pMonAdapter =
1522 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1523 if( pMonAdapter == NULL )
1524 {
1525 hddLog( LOGE, "Not able to get Monitor Adapter");
1526 cfgState->skb = NULL;
1527 vos_mem_free( cfgState->buf );
1528 cfgState->buf = NULL;
1529 complete(&pAdapter->tx_action_cnf_event);
1530 return;
1531 }
1532 /* Send TX completion feedback over monitor interface. */
1533 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1534 cfgState->skb = NULL;
1535 vos_mem_free( cfgState->buf );
1536 cfgState->buf = NULL;
1537 /* Look for the next Mgmt packet to TX */
1538 hdd_mon_tx_mgmt_pkt(pAdapter);
1539 }
1540 complete(&pAdapter->tx_action_cnf_event);
1541}
1542
1543/**
1544 * hdd_setP2pNoa
1545 *
1546 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301547 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001548 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1549 *
1550 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301551 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001552 *
1553 *ASSUMPTIONS:
1554 *
1555 *
1556 *NOTE:
1557 *
1558 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301559 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001560 *
1561 * @return Status
1562 */
1563
1564int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1565{
1566 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1567 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1568 VOS_STATUS status = VOS_STATUS_SUCCESS;
1569 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001570 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001571 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001572 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001573
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001574 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001575 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301576 {
1577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1578 "%s: strnchr failed to find delimeter",__func__);
1579 return -EINVAL;
1580 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001581 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001582 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1583 if (ret < 3)
1584 {
1585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1586 "%s: P2P_SET GO NoA: fail to read param "
1587 "count=%d duration=%d interval=%d \n",
1588 __func__, count, start_time, duration);
1589 return -EINVAL;
1590 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001592 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001593 __func__, count, start_time, duration);
1594 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001595 /* PS Selection
1596 * Periodic NoA (2)
1597 * Single NOA (4)
1598 */
1599 NoA.opp_ps = 0;
1600 NoA.ctWindow = 0;
1601 if (count == 1)
1602 {
1603 NoA.duration = 0;
1604 NoA.single_noa_duration = duration;
1605 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1606 }
1607 else
1608 {
1609 NoA.duration = duration;
1610 NoA.single_noa_duration = 0;
1611 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1612 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001613 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001614 NoA.count = count;
1615 NoA.sessionid = pAdapter->sessionId;
1616
1617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1618 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1619 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001620 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001621 NoA.ctWindow, NoA.duration, NoA.interval,
1622 NoA.count, NoA.single_noa_duration,
1623 NoA.psSelection);
1624
1625 sme_p2pSetPs(hHal, &NoA);
1626 return status;
1627}
1628
1629/**
1630 * hdd_setP2pOpps
1631 *
1632 *FUNCTION:
1633 * This function is called from hdd_hostapd_ioctl function when Driver
1634 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1635 *
1636 *LOGIC:
1637 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1638 *
1639 *ASSUMPTIONS:
1640 *
1641 *
1642 *NOTE:
1643 *
1644 * @param dev Pointer to net device structure
1645 * @param command Pointer to command
1646 *
1647 * @return Status
1648 */
1649
1650int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1651{
1652 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1653 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1654 VOS_STATUS status = VOS_STATUS_SUCCESS;
1655 tP2pPsConfig NoA;
1656 char *param;
1657 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001658 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001659
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001660 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301662 {
1663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1664 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001665 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301666 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001667 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001668 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1669 if (ret < 3)
1670 {
1671 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1672 "%s: P2P_SET GO PS: fail to read param "
1673 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1674 __func__, legacy_ps, opp_ps, ctwindow);
1675 return -EINVAL;
1676 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001677 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001678 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001679 __func__, legacy_ps, opp_ps, ctwindow);
1680
1681 /* PS Selection
1682 * Opportunistic Power Save (1)
1683 */
1684
1685 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1686 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301687 * values are coming from wpa_supplicant as -1.
1688 * Example : User want to set ctWindow with 30 then wpa_cli command :
1689 * P2P_SET ctwindow 30
1690 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001691 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301692 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001693 if (ctwindow != -1)
1694 {
1695
1696 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001697 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001698 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1699
1700 if (ctwindow != pAdapter->ctw)
1701 {
1702 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301703
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 if(pAdapter->ops)
1705 {
1706 NoA.opp_ps = pAdapter->ops;
1707 NoA.ctWindow = pAdapter->ctw;
1708 NoA.duration = 0;
1709 NoA.single_noa_duration = 0;
1710 NoA.interval = 0;
1711 NoA.count = 0;
1712 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1713 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301714
Jeff Johnson295189b2012-06-20 16:38:30 -07001715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1716 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1717 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001718 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001719 NoA.ctWindow, NoA.duration, NoA.interval,
1720 NoA.count, NoA.single_noa_duration,
1721 NoA.psSelection);
1722
1723 sme_p2pSetPs(hHal, &NoA);
1724 }
1725 return 0;
1726 }
1727 }
1728
1729 if (opp_ps != -1)
1730 {
1731 pAdapter->ops = opp_ps;
1732
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301733 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001734 {
1735 NoA.opp_ps = opp_ps;
1736 NoA.ctWindow = pAdapter->ctw;
1737 NoA.duration = 0;
1738 NoA.single_noa_duration = 0;
1739 NoA.interval = 0;
1740 NoA.count = 0;
1741 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1742 NoA.sessionid = pAdapter->sessionId;
1743
1744 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1745 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1746 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001747 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001748 NoA.ctWindow, NoA.duration, NoA.interval,
1749 NoA.count, NoA.single_noa_duration,
1750 NoA.psSelection);
1751
1752 sme_p2pSetPs(hHal, &NoA);
1753 }
1754 }
1755 return status;
1756}
1757
1758int hdd_setP2pPs( struct net_device *dev, void *msgData )
1759{
1760 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1761 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1762 VOS_STATUS status = VOS_STATUS_SUCCESS;
1763 tP2pPsConfig NoA;
1764 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1765
1766 NoA.opp_ps = pappNoA->opp_ps;
1767 NoA.ctWindow = pappNoA->ctWindow;
1768 NoA.duration = pappNoA->duration;
1769 NoA.interval = pappNoA->interval;
1770 NoA.count = pappNoA->count;
1771 NoA.single_noa_duration = pappNoA->single_noa_duration;
1772 NoA.psSelection = pappNoA->psSelection;
1773 NoA.sessionid = pAdapter->sessionId;
1774
1775 sme_p2pSetPs(hHal, &NoA);
1776 return status;
1777}
Jeff Johnson295189b2012-06-20 16:38:30 -07001778
1779static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1780{
1781 tANI_U8 sessionType;
1782
1783 switch( type )
1784 {
1785 case NL80211_IFTYPE_AP:
1786 sessionType = WLAN_HDD_SOFTAP;
1787 break;
1788 case NL80211_IFTYPE_P2P_GO:
1789 sessionType = WLAN_HDD_P2P_GO;
1790 break;
1791 case NL80211_IFTYPE_P2P_CLIENT:
1792 sessionType = WLAN_HDD_P2P_CLIENT;
1793 break;
1794 case NL80211_IFTYPE_STATION:
1795 sessionType = WLAN_HDD_INFRA_STATION;
1796 break;
1797 case NL80211_IFTYPE_MONITOR:
1798 sessionType = WLAN_HDD_MONITOR;
1799 break;
1800 default:
1801 sessionType = WLAN_HDD_INFRA_STATION;
1802 break;
1803 }
1804
1805 return sessionType;
1806}
1807
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001808#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301809struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001810 struct wiphy *wiphy, const char *name,
1811 enum nl80211_iftype type,
1812 u32 *flags, struct vif_params *params )
1813#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301814struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001815 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1816 u32 *flags, struct vif_params *params )
1817#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301818struct net_device* __wlan_hdd_add_virtual_intf(
Jeff Johnson295189b2012-06-20 16:38:30 -07001819 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1820 u32 *flags, struct vif_params *params )
1821#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301822int __wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
Jeff Johnson295189b2012-06-20 16:38:30 -07001823 enum nl80211_iftype type,
1824 u32 *flags, struct vif_params *params )
1825#endif
1826{
1827 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301828 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301829 hdd_scaninfo_t *pScanInfo = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001830 ENTER();
1831
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301832 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1833 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301834 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1835 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1836 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001837 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001838 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001839 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05301840#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1841 return ERR_PTR(-EINVAL);
1842#else
1843 return -EAGAIN;
1844#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001845 }
1846
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001847 if (pHddCtx->isLogpInProgress)
1848 {
1849 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1850 "%s:LOGP in Progress. Ignore!!!", __func__);
1851#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301852 return ERR_PTR(-EINVAL);
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001853#else
1854 return -EAGAIN;
1855#endif
1856 }
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301857
1858 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1859 pScanInfo = &pHddCtx->scan_info;
1860 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1861 (pHddCtx->scan_info.mScanPending))
1862 {
1863 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1864 eCSR_SCAN_ABORT_DEFAULT);
1865 hddLog(VOS_TRACE_LEVEL_INFO,
1866 "%s: Abort Scan while adding virtual interface",__func__);
1867 }
1868
1869 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05301870 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
1871 ((NL80211_IFTYPE_P2P_GO == type) ||
1872 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07001873 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001874 /* Generate the P2P Interface Address. this address must be
1875 * different from the P2P Device Address.
1876 */
1877 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
1878 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301879 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001880 wlan_hdd_get_session_type(type),
1881 name, p2pDeviceAddress.bytes,
1882 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07001883 }
1884 else
1885 {
1886 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
1887 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
1888 }
1889
1890 if( NULL == pAdapter)
1891 {
1892 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
1893#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05301894 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001895#else
1896 return -EINVAL;
1897#endif
1898 }
1899 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001900#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1901 return pAdapter->dev->ieee80211_ptr;
1902#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07001903 return pAdapter->dev;
1904#else
1905 return 0;
1906#endif
1907}
1908
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301909#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
1910struct wireless_dev* wlan_hdd_add_virtual_intf(
1911 struct wiphy *wiphy, const char *name,
1912 enum nl80211_iftype type,
1913 u32 *flags, struct vif_params *params )
1914#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1915struct wireless_dev* wlan_hdd_add_virtual_intf(
1916 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1917 u32 *flags, struct vif_params *params )
1918#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1919struct net_device* wlan_hdd_add_virtual_intf(
1920 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1921 u32 *flags, struct vif_params *params )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001922#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301923int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
1924 enum nl80211_iftype type,
1925 u32 *flags, struct vif_params *params )
1926#endif
1927{
1928#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)))
1929 struct wireless_dev* wdev;
1930#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1931 struct net_device* ndev;
1932#else
1933 int ret;
1934#endif
1935 vos_ssr_protect(__func__);
1936#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1937 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1938 vos_ssr_unprotect(__func__);
1939 return wdev;
1940#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1941 ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1942 vos_ssr_unprotect(__func__);
1943 return ndev;
1944#else
1945 ret = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
1946 vos_ssr_unprotect(__func__);
1947 return ret;
1948#endif
1949}
1950
1951#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1952int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1953#else
1954int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001955#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001956{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001957#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1958 struct net_device *dev = wdev->netdev;
1959#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301960 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301961 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301962 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1963 int status;
1964 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07001965
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301966 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1967 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1968 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301969 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
1970 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07001971
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301972 status = wlan_hdd_validate_context(pHddCtx);
1973
1974 if (0 != status)
1975 {
1976 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1977 "%s: HDD context is not valid", __func__);
1978 return status;
1979 }
1980
1981 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07001982 pVirtAdapter->macAddressCurrent.bytes );
1983
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05301984 hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301985 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
1986 EXIT();
1987 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001988}
1989
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301990#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1991int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
1992#else
1993int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
1994#endif
1995{
1996 int ret;
1997
1998 vos_ssr_protect(__func__);
1999#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2000 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
2001#else
2002 ret = __wlan_hdd_del_virtual_intf(wiphy, dev);
2003#endif
2004 vos_ssr_unprotect(__func__);
2005
2006 return ret;
2007}
2008
Jeff Johnson295189b2012-06-20 16:38:30 -07002009void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002010 tANI_U32 nFrameLength,
2011 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302012 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07002013{
2014 //Indicate a Frame over Monitor Intf.
2015 int rxstat;
2016 struct sk_buff *skb = NULL;
2017 int needed_headroom = 0;
2018 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
2019 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002020#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002021#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2022 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
2023#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002024#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002025 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
2026
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002027 if (NULL == pbFrames)
2028 {
2029 hddLog(LOGE, FL("NULL frame pointer"));
2030 return;
2031 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002032
2033 /* room for the radiotap header based on driver features
2034 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
2035 * RX flags.
2036 * */
2037 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
2038
2039 //alloc skb here
2040 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
2041 if (unlikely(NULL == skb))
2042 {
2043 hddLog( LOGW, FL("Unable to allocate skb"));
2044 return;
2045 }
2046 skb_reserve(skb, VPKT_SIZE_BUFFER);
2047 if (unlikely(skb_headroom(skb) < nFrameLength))
2048 {
2049 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2050 "HDD [%d]: Insufficient headroom, "
2051 "head[%p], data[%p], req[%d]",
2052 __LINE__, skb->head, skb->data, nFrameLength);
2053 kfree_skb(skb);
2054 return ;
2055 }
2056 // actually push the data
2057 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
2058 /* prepend radiotap information */
2059 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
2060 {
2061 hddLog( LOGE, FL("Not Able Add Radio Tap"));
2062 //free skb
2063 kfree_skb(skb);
2064 return ;
2065 }
2066
2067 skb_reset_mac_header( skb );
2068 skb->dev = pMonAdapter->dev;
2069 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002070 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002071#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002072#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002073 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002074#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002075#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002076 rxstat = netif_rx_ni(skb);
2077 if( NET_RX_SUCCESS == rxstat )
2078 {
2079 hddLog( LOG1, FL("Success"));
2080 }
2081 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302082 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07002083
2084 return ;
2085}
2086
2087void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302088 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07002089 tANI_U8* pbFrames,
2090 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05302091 tANI_U32 rxChan,
2092 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07002093{
2094 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302095 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07002096 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002097 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07002098 tActionFrmType actionFrmType;
2099 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302100 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05302101 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302102 VOS_STATUS status;
2103 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002104
Arif Hussain6d2a3322013-11-17 19:50:10 -08002105 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002106 __func__, frameType, nFrameLength);
2107
2108 if (NULL == pAdapter)
2109 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002110 hddLog(LOGE, FL("pAdapter is NULL"));
2111 return;
2112 }
2113
2114 if (0 == nFrameLength)
2115 {
2116 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2117 return;
2118 }
2119
2120 if (NULL == pbFrames)
2121 {
2122 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002123 return;
2124 }
2125
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002126 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2127 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2128
2129 /* Get pAdapter from Destination mac address of the frame */
2130 if ((type == SIR_MAC_MGMT_FRAME) &&
2131 (subType != SIR_MAC_MGMT_PROBE_REQ))
2132 {
2133 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
2134 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
2135 if (NULL == pAdapter)
2136 {
2137 /* Under assumtion that we don't receive any action frame
2138 * with BCST as destination we dropping action frame
2139 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08002140 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
2141 MAC_ADDRESS_STR ,
2142 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
2143 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08002144 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002145 return;
2146 }
2147 }
2148
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002149
Jeff Johnson295189b2012-06-20 16:38:30 -07002150 if (NULL == pAdapter->dev)
2151 {
2152 hddLog( LOGE, FL("pAdapter->dev is NULL"));
2153 return;
2154 }
2155
2156 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2157 {
2158 hddLog( LOGE, FL("pAdapter has invalid magic"));
2159 return;
2160 }
2161
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302162 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2163 if (NULL == pHddCtx)
2164 {
2165 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
2166 return;
2167 }
2168
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002169 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2170 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07002171 {
2172 hdd_adapter_t *pMonAdapter =
2173 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
2174
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002175 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07002176 {
2177 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
2178 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
2179 pbFrames, frameType);
2180 return;
2181 }
2182 }
2183
2184 //Channel indicated may be wrong. TODO
2185 //Indicate an action frame.
2186 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
2187 {
2188 freq = ieee80211_channel_to_frequency( rxChan,
2189 IEEE80211_BAND_2GHZ);
2190 }
2191 else
2192 {
2193 freq = ieee80211_channel_to_frequency( rxChan,
2194 IEEE80211_BAND_5GHZ);
2195 }
2196
Jeff Johnsone7245742012-09-05 17:12:55 -07002197 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302198 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302199
2200 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002201 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07002202 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002203 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
2204 {
2205 // public action frame
2206 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08002207 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 -08002208 // P2P action frames
2209 {
2210 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002211 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002212#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002213 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
2214 {
2215 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
2216 actionFrmType);
2217 }
2218 else
2219 {
2220 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
2221 p2p_action_frame_type[actionFrmType]);
2222 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
2223 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2224 {
2225 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
2226 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002227 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002228 }
2229 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
2230 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
2231 {
2232 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08002233 hddLog(LOGE,"[P2P State]GO negotiation progress to "
2234 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002235 }
2236 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
2237 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2238 {
2239 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
2240 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
2241 " completed state Autonomous GO formation");
2242 }
2243 }
2244#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302245 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
2246 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
2247 {
2248 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
2249 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
2250 actionFrmType == WLAN_HDD_INVITATION_REQ ||
2251 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
2252 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
2253 {
2254 hddLog( LOG1, "Extend RoC timer on reception of"
2255 " Action Frame");
2256 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
2257 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
2258 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
2259 else
2260 extend_time = ACTION_FRAME_DEFAULT_WAIT;
2261 if (completion_done(&pAdapter->rem_on_chan_ready_event))
2262 {
2263 vos_timer_stop(
2264 &pRemainChanCtx->hdd_remain_on_chan_timer);
2265 status = vos_timer_start(
2266 &pRemainChanCtx->hdd_remain_on_chan_timer,
2267 extend_time);
2268 if (status != VOS_STATUS_SUCCESS)
2269 {
2270 hddLog( LOGE, "ROC timer start failed");
2271 }
2272 }
2273 else
2274 {
2275 // Buffer Packet
2276 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2277 {
2278 pRemainChanCtx->action_pkt_buff.frame_length =
2279 nFrameLength;
2280 pRemainChanCtx->action_pkt_buff.freq = freq;
2281 pRemainChanCtx->action_pkt_buff.frame_ptr
2282 = vos_mem_malloc(nFrameLength);
2283 vos_mem_copy(
2284 pRemainChanCtx->action_pkt_buff.frame_ptr,
2285 pbFrames, nFrameLength);
2286 hddLog( LOGE,"%s:"
2287 "Action Pkt Cached successfully !!!", __func__);
2288 }
2289 else
2290 {
2291 hddLog( LOGE,"%s:"
2292 "Frames are pending. dropping frame !!!",
2293 __func__);
2294 }
2295 return;
2296 }
2297 }
2298 }
2299 if (pRemainChanCtx != NULL &&
2300 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2301 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2302 hddLog( LOG1, "%s:"
2303 "Rcvd action frame after timer expired ", __func__);
2304
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302305 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2306 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2307 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2308 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2309 {
2310 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2311 __func__);
2312 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002313 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002314 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002315#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002316 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 -07002317 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002318 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
2319#ifdef WLAN_FEATURE_TDLS_DEBUG
2320 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2321 MAC_ADDR_ARRAY(mac),rxRssi);
2322#endif
2323 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2324 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002325 }
2326#endif
2327 }
Kaushik, Sushant507a8612014-10-21 17:00:55 +05302328
2329 pScanInfo = &pHddCtx->scan_info;
2330 if ((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2331 {
2332 hddLog(LOGE,"Action frame received when Scanning is in"
2333 " progress. Abort Scan.");
2334 hdd_abort_mac_scan(pAdapter->pHddCtx,
2335 pScanInfo->sessionId,
2336 eCSR_SCAN_ABORT_DEFAULT);
2337 }
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002338#ifdef WLAN_FEATURE_TDLS_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002339 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2340 {
2341 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2342 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2343 {
2344 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] unknown[%d] <--- OTA",
2345 actionFrmType);
2346 }
2347 else
2348 {
2349 hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] %s <--- OTA",
2350 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002351 }
2352 }
2353#endif
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002354 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2355 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2356 {
Kumar Anand82c009f2014-05-29 00:29:42 -07002357 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
2358 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002359 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002360 }
2361
Jeff Johnson295189b2012-06-20 16:38:30 -07002362 //Indicate Frame Over Normal Interface
2363 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
2364
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002365#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2366 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2367 pbFrames, nFrameLength,
2368 GFP_ATOMIC );
2369#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002370 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2371 pbFrames, nFrameLength,
2372 GFP_ATOMIC );
2373#else
2374 cfg80211_rx_mgmt( pAdapter->dev, freq,
2375 pbFrames, nFrameLength,
2376 GFP_ATOMIC );
2377#endif //LINUX_VERSION_CODE
2378}
2379
2380/*
2381 * ieee80211_add_rx_radiotap_header - add radiotap header
2382 */
2383static int hdd_wlan_add_rx_radiotap_hdr (
2384 struct sk_buff *skb, int rtap_len, int flag )
2385{
2386 u8 rtap_temp[20] = {0};
2387 struct ieee80211_radiotap_header *rthdr;
2388 unsigned char *pos;
2389 u16 rx_flags = 0;
2390
2391 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2392
2393 /* radiotap header, set always present flags */
2394 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2395 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2396 rthdr->it_len = cpu_to_le16(rtap_len);
2397
2398 pos = (unsigned char *) (rthdr + 1);
2399
2400 /* the order of the following fields is important */
2401
2402 /* IEEE80211_RADIOTAP_FLAGS */
2403 *pos = 0;
2404 pos++;
2405
2406 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2407 /* ensure 2 byte alignment for the 2 byte field as required */
2408 if ((pos - (u8 *)rthdr) & 1)
2409 pos++;
2410 put_unaligned_le16(rx_flags, pos);
2411 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302412
Jeff Johnson295189b2012-06-20 16:38:30 -07002413 // actually push the data
2414 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2415
2416 return 0;
2417}
2418
2419static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2420 hdd_cfg80211_state_t* cfgState,
2421 tANI_BOOLEAN actionSendSuccess )
2422{
2423 struct ieee80211_radiotap_header *rthdr;
2424 unsigned char *pos;
2425 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002426#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002427#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2428 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2429#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002430#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002431
2432 /* 2 Byte for TX flags and 1 Byte for Retry count */
2433 u32 rtHdrLen = sizeof(*rthdr) + 3;
2434
2435 u8 *data;
2436
2437 /* We have to return skb with Data starting with MAC header. We have
2438 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2439 * entire skb->len from skb and then we will push cfgState->buf to skb
2440 * */
2441 if( NULL == skb_pull(skb, skb->len) )
2442 {
2443 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2444 kfree_skb(cfgState->skb);
2445 return;
2446 }
2447
2448 data = skb_push( skb, cfgState->len );
2449
2450 if (data == NULL)
2451 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002452 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002453 kfree_skb( cfgState->skb );
2454 return;
2455 }
2456
2457 memcpy( data, cfgState->buf, cfgState->len );
2458
2459 /* send frame to monitor interfaces now */
2460 if( skb_headroom(skb) < rtHdrLen )
2461 {
2462 hddLog( LOGE, FL("No headroom for rtap header"));
2463 kfree_skb(cfgState->skb);
2464 return;
2465 }
2466
2467 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2468
2469 memset( rthdr, 0, rtHdrLen );
2470 rthdr->it_len = cpu_to_le16( rtHdrLen );
2471 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2472 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2473 );
2474
2475 pos = (unsigned char *)( rthdr+1 );
2476
2477 // Fill TX flags
2478 *pos = actionSendSuccess;
2479 pos += 2;
2480
2481 // Fill retry count
2482 *pos = 0;
2483 pos++;
2484
2485 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002486 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002487 skb->pkt_type = PACKET_OTHERHOST;
2488 skb->protocol = htons(ETH_P_802_2);
2489 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002490#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002491#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Amar Singhal6144c002013-05-03 16:11:42 -07002492 wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION));
Jeff Johnsone7245742012-09-05 17:12:55 -07002493#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002494#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002495 if (in_interrupt())
2496 netif_rx( skb );
2497 else
2498 netif_rx_ni( skb );
2499
2500 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05302501 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302502 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002503
2504}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302505
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05302506void hdd_p2p_roc_work_queue(struct work_struct *work)
2507{
2508 hdd_adapter_t *pAdapter = container_of(to_delayed_work(work), hdd_adapter_t, roc_work);
2509 hddLog( VOS_TRACE_LEVEL_INFO, FL("%s: "), __func__);
2510 wlan_hdd_p2p_start_remain_on_channel(pAdapter);
2511 return;
2512}
2513