blob: 23547e9c8811aaab711c9d76da9ac00dc9451092 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302 * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/**========================================================================
29
30 \file wlan_hdd_p2p.c
31
32 \brief WLAN Host Device Driver implementation for P2P commands interface
33
Jeff Johnson295189b2012-06-20 16:38:30 -070034
35 ========================================================================*/
Jeff Johnson295189b2012-06-20 16:38:30 -070036
37#include <wlan_hdd_includes.h>
38#include <wlan_hdd_hostapd.h>
39#include <net/cfg80211.h>
40#include "sme_Api.h"
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -070041#include "sme_QosApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070042#include "wlan_hdd_p2p.h"
43#include "sapApi.h"
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +053044#include "wlan_hdd_main.h"
Daram Sudha1f7e0e92013-12-17 07:52:31 +053045#include "vos_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070046#include <linux/netdevice.h>
47#include <linux/skbuff.h>
48#include <linux/etherdevice.h>
49#include <net/ieee80211_radiotap.h>
Hoonki Lee1090c6a2013-01-16 17:40:54 -080050#ifdef FEATURE_WLAN_TDLS
51#include "wlan_hdd_tdls.h"
52#endif
Sushant Kaushik4b7cb302014-01-06 17:45:01 +053053#include "wlan_hdd_trace.h"
54#include "vos_types.h"
55#include "vos_trace.h"
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +053056#include "vos_sched.h"
57
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -080058//Ms to Micro Sec
59#define MS_TO_MUS(x) ((x)*1000);
Daram Sudha1f7e0e92013-12-17 07:52:31 +053060tANI_U8* hdd_getActionString( tANI_U16 MsgType )
61{
62 switch (MsgType)
63 {
64 CASE_RETURN_STRING(SIR_MAC_ACTION_SPECTRUM_MGMT);
65 CASE_RETURN_STRING(SIR_MAC_ACTION_QOS_MGMT);
66 CASE_RETURN_STRING(SIR_MAC_ACTION_DLP);
67 CASE_RETURN_STRING(SIR_MAC_ACTION_BLKACK);
68 CASE_RETURN_STRING(SIR_MAC_ACTION_PUBLIC_USAGE);
69 CASE_RETURN_STRING(SIR_MAC_ACTION_RRM);
70 CASE_RETURN_STRING(SIR_MAC_ACTION_FAST_BSS_TRNST);
71 CASE_RETURN_STRING(SIR_MAC_ACTION_HT);
72 CASE_RETURN_STRING(SIR_MAC_ACTION_SA_QUERY);
73 CASE_RETURN_STRING(SIR_MAC_ACTION_PROT_DUAL_PUB);
74 CASE_RETURN_STRING(SIR_MAC_ACTION_WNM);
75 CASE_RETURN_STRING(SIR_MAC_ACTION_UNPROT_WNM);
76 CASE_RETURN_STRING(SIR_MAC_ACTION_TDLS);
77 CASE_RETURN_STRING(SIR_MAC_ACITON_MESH);
78 CASE_RETURN_STRING(SIR_MAC_ACTION_MULTIHOP);
79 CASE_RETURN_STRING(SIR_MAC_SELF_PROTECTED);
80 CASE_RETURN_STRING(SIR_MAC_ACTION_WME);
81 CASE_RETURN_STRING(SIR_MAC_ACTION_VHT);
82 default:
83 return ("UNKNOWN");
84 }
85}
86
87
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -070088#ifdef WLAN_FEATURE_P2P_DEBUG
89#define MAX_P2P_ACTION_FRAME_TYPE 9
90const char *p2p_action_frame_type[]={"GO Negotiation Request",
91 "GO Negotiation Response",
92 "GO Negotiation Confirmation",
93 "P2P Invitation Request",
94 "P2P Invitation Response",
95 "Device Discoverability Request",
96 "Device Discoverability Response",
97 "Provision Discovery Request",
98 "Provision Discovery Response"};
99
100/* We no need to protect this variable since
101 * there is no chance of race to condition
102 * and also not make any complicating the code
103 * just for debugging log
104 */
105tP2PConnectionStatus globalP2PConnectionStatus = P2P_NOT_ACTIVE;
106
107#endif
Hoonki Lee1090c6a2013-01-16 17:40:54 -0800108#define MAX_TDLS_ACTION_FRAME_TYPE 11
109const char *tdls_action_frame_type[] = {"TDLS Setup Request",
110 "TDLS Setup Response",
111 "TDLS Setup Confirm",
112 "TDLS Teardown",
113 "TDLS Peer Traffic Indication",
114 "TDLS Channel Switch Request",
115 "TDLS Channel Switch Response",
116 "TDLS Peer PSM Request",
117 "TDLS Peer PSM Response",
118 "TDLS Peer Traffic Response",
119 "TDLS Discovery Request" };
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -0700120
Jeff Johnson295189b2012-06-20 16:38:30 -0700121extern struct net_device_ops net_ops_struct;
122
123static int hdd_wlan_add_rx_radiotap_hdr( struct sk_buff *skb,
124 int rtap_len, int flag );
125
126static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
127 hdd_cfg80211_state_t* cfgState,
128 tANI_BOOLEAN actionSendSuccess );
129
130static void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Rashmi Ramannac7744532013-10-06 16:49:08 +0530131 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -0700132 tANI_U8* pbFrames,
133 tANI_U8 frameType );
vamsi9bd92b72013-12-26 14:11:29 +0530134
135static v_BOOL_t hdd_p2p_is_action_type_rsp( const u8 *buf )
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530136{
vamsi9bd92b72013-12-26 14:11:29 +0530137 tActionFrmType actionFrmType;
138 const u8 *ouiPtr;
139
140 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
141 WLAN_HDD_PUBLIC_ACTION_FRAME ) {
142 return VOS_FALSE;
143 }
144
145 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] !=
146 WLAN_HDD_VENDOR_SPECIFIC_ACTION ) {
147 return VOS_FALSE;
148 }
149
150 ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET];
151
152 if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) {
153 return VOS_FALSE;
154 }
155
156 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] !=
157 WLAN_HDD_WFA_P2P_OUI_TYPE ) {
158 return VOS_FALSE;
159 }
160
Ahmad Kholaife5ec2cd2014-03-19 13:22:04 +0530161 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
vamsi9bd92b72013-12-26 14:11:29 +0530162 if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
163 actionFrmType != WLAN_HDD_GO_NEG_REQ &&
164 actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
165 actionFrmType != WLAN_HDD_PROV_DIS_REQ )
166 return VOS_TRUE;
167 else
168 return VOS_FALSE;
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530169}
Jeff Johnson295189b2012-06-20 16:38:30 -0700170
Jeff Johnson295189b2012-06-20 16:38:30 -0700171eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
172 eHalStatus status )
173{
174 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700175 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
176 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530177 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700178
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530179 if (pHddCtx == NULL)
180 {
181 hddLog(LOGE, "%s: Hdd Context is NULL", __func__);
182 return eHAL_STATUS_FAILURE;
183 }
184 if (pRemainChanCtx == NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700185 {
186 hddLog( LOGW,
187 "%s: No Rem on channel pending for which Rsp is received", __func__);
188 return eHAL_STATUS_SUCCESS;
189 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530190
191 mutex_lock(&pHddCtx->roc_lock);
Rashmi Ramannac7744532013-10-06 16:49:08 +0530192 hddLog( VOS_TRACE_LEVEL_INFO,
193 "Received ROC rsp (request type %d, channel %d, cookie %llu",
194 pRemainChanCtx->rem_on_chan_request,
195 pRemainChanCtx->chan.center_freq,
196 pRemainChanCtx->cookie);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530197 vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
198 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530199 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530200 if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
Jeff Johnson295189b2012-06-20 16:38:30 -0700201 {
202 if( cfgState->buf )
203 {
Agrawal Ashishb10d0392015-08-06 16:18:20 +0530204 hddLog( LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -0700205 "%s: We need to receive yet an ack from one of tx packet",
206 __func__);
207 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800208 cfg80211_remain_on_channel_expired(
209#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
210 pRemainChanCtx->dev->ieee80211_ptr,
211#else
212 pRemainChanCtx->dev,
213#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700214 pRemainChanCtx->cookie,
215 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700216#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
217 pRemainChanCtx->chan_type,
218#endif
219 GFP_KERNEL);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530220 pAdapter->lastRocTs = vos_timer_get_system_time();
Jeff Johnson295189b2012-06-20 16:38:30 -0700221 }
222
Jeff Johnson295189b2012-06-20 16:38:30 -0700223
224 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700225 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
226 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700227 )
228 {
229 tANI_U8 sessionId = pAdapter->sessionId;
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800230 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
231 {
232 sme_DeregisterMgmtFrame(
233 hHal, sessionId,
234 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
235 NULL, 0 );
236 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700237 }
Abhishek Singh36b7c532015-03-13 15:50:54 +0530238 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -0700239 {
240 WLANSAP_DeRegisterMgmtFrame(
241 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
242 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
243 NULL, 0 );
244 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530245 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
246 && pRemainChanCtx->action_pkt_buff.frame_length != 0)
247 {
248 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
249 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800250 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800251 pRemainChanCtx = NULL;
Ratheesh S P8278de82015-07-10 18:44:21 +0530252 cfgState->remain_on_chan_ctx = NULL;
Deepthi Gowri3e672f02015-01-30 17:04:08 +0530253 if (eHAL_STATUS_SUCCESS != status)
254 complete(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 complete(&pAdapter->cancel_rem_on_chan_var);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530256 pAdapter->is_roc_inprogress = FALSE;
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530257 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Jeff Johnson295189b2012-06-20 16:38:30 -0700258 return eHAL_STATUS_SUCCESS;
259}
260
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530261VOS_STATUS wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700262{
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530264 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530265 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700267
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530268 if (NULL == pHddCtx)
269 {
270 hddLog(LOGE, "%s: HddCtx is NULL", __func__);
271 return VOS_STATUS_E_FAILURE;
272 }
273
274 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700275 if(cfgState->remain_on_chan_ctx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700276 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530277 if(VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
278 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
279 {
280 hddLog(VOS_TRACE_LEVEL_INFO,
281 "Cancel Existing ROC (cookie=%llu)",
282 cfgState->remain_on_chan_ctx->cookie);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700283
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530284 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
285 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530286 /* Wait till remain on channel ready indication before issuing cancel
287 * remain on channel request, otherwise if remain on channel not
288 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700289 * will be in unknown state.
290 */
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530291 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress != TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 {
Deepthi Gowrief88a5f2015-04-06 14:41:46 +0530293 mutex_unlock(&pHddCtx->roc_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530294 status = wait_for_completion_interruptible_timeout(
295 &pAdapter->rem_on_chan_ready_event,
296 msecs_to_jiffies(WAIT_REM_CHAN_READY));
297 if (0 >= status)
298 {
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +0530299 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530300 hddLog( LOGE,
301 "%s: timeout waiting for remain on channel"
302 " ready indication %d",
303 __func__, status);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530304 return VOS_STATUS_E_FAILURE;
305 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700306
Deepthi Gowrief88a5f2015-04-06 14:41:46 +0530307 mutex_lock(&pHddCtx->roc_lock);
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530308 /* Check again if cancel remain on channel is started.
309 * If its started wait for its completiona and return.
310 */
311 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
312 {
313 mutex_unlock(&pHddCtx->roc_lock);
314 hddLog( LOG1,
315 "ROC timer cancellation in progress,"
316 " wait for completion");
317 status = wait_for_completion_interruptible_timeout(
318 &pAdapter->cancel_rem_on_chan_var,
319 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
320 if (0 >= status)
321 {
322 hddLog( LOGE,
323 "%s:wait on cancel_rem_on_chan_var failed %d",
324 __func__, status);
325 return VOS_STATUS_E_FAILURE;
326 }
327 return VOS_STATUS_SUCCESS;
328 }
329 else
330 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530331
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530332 mutex_unlock(&pHddCtx->roc_lock);
333 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
334
335 /* Issue abort remain on chan request to sme.
336 * The remain on channel callback will make sure the remain_on_chan
337 * expired event is sent.
338 */
339 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Abhishek Singh36b7c532015-03-13 15:50:54 +0530340 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
341 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ))
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530342 {
343 if (eHAL_STATUS_SUCCESS !=
344 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
Deepthi Gowri70498252015-01-20 15:56:45 +0530345 pAdapter->sessionId ))
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530346 {
347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
348 FL("Failed to Cancel Remain on Channel"));
349 }
350 }
351 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
352 {
353 WLANSAP_CancelRemainOnChannel(
354 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
355 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700356
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530357 status = wait_for_completion_interruptible_timeout(
358 &pAdapter->cancel_rem_on_chan_var,
359 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
360 if (0 >= status)
361 {
362 hddLog( LOGE,
363 "%s: timeout waiting for cancel remain on channel"
364 " ready indication %d",
365 __func__, status);
366 }
367 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530368 }
369 else
370 {
371 hddLog( LOG1,
372 "ROC timer cancellation in progress,"
373 " wait for completion");
374 mutex_unlock(&pHddCtx->roc_lock);
375 status = wait_for_completion_interruptible_timeout(
376 &pAdapter->cancel_rem_on_chan_var,
377 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
378 if (0 >= status)
379 {
380 hddLog( LOGE,
381 "%s:wait on cancel_rem_on_chan_var failed %d",
382 __func__, status);
383 return VOS_STATUS_E_FAILURE;
384 }
385 return VOS_STATUS_SUCCESS;
386 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700387 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530388 else
389 {
390 hddLog(LOG1,
391 "%s: remain_on_chan_ctx is NULL", __func__);
392 mutex_unlock(&pHddCtx->roc_lock);
393 }
394 return VOS_STATUS_SUCCESS;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700395}
396
397int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
398{
399 int status = 0;
400 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
401
402 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
403 {
404 //Cancel Existing Remain On Channel
405 //If no action frame is pending
406 if( cfgState->remain_on_chan_ctx != NULL)
407 {
408 //Check whether Action Frame is pending or not
409 if( cfgState->buf == NULL)
410 {
411 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
412 }
413 else
414 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530415 hddLog(VOS_TRACE_LEVEL_DEBUG,
416 "Cannot Cancel Existing Remain on Channel");
Jeff Johnson32d95a32012-09-10 13:15:23 -0700417 status = -EBUSY;
418 }
419 }
420 }
421 return status;
422}
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530423void wlan_hdd_remain_on_chan_timeout(void *data)
424{
425 hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
426 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
427 hdd_cfg80211_state_t *cfgState;
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530428 hdd_context_t *pHddCtx;
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +0530429
430 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530431 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +0530432 hddLog( LOGE, FL("pAdapter is invalid %p !!!"), pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530433 return;
434 }
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530435 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530436 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
437 pRemainChanCtx = cfgState->remain_on_chan_ctx;
438 if (NULL == pRemainChanCtx)
439 {
440 hddLog( LOGE, FL("No Remain on channel is pending"));
441 return;
442 }
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530443 mutex_lock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530444 if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
445 {
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530446 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530447 hddLog( LOGE, FL("Cancellation already in progress"));
448 return;
449 }
450
451 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530452 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530453 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
454 hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
Abhishek Singh36b7c532015-03-13 15:50:54 +0530455 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
456 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530457 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
458 )
459 {
Deepthi Gowri70498252015-01-20 15:56:45 +0530460 if (eHAL_STATUS_SUCCESS !=
461 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
462 pAdapter->sessionId ))
463 {
464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
465 FL("Failed to Cancel Remain on Channel"));
466 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530467 }
Abhishek Singh36b7c532015-03-13 15:50:54 +0530468 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530469 {
Deepthi Gowri70498252015-01-20 15:56:45 +0530470 WLANSAP_CancelRemainOnChannel(
471 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530472 }
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530473 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530474}
Jeff Johnson32d95a32012-09-10 13:15:23 -0700475
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530476static int wlan_hdd_p2p_start_remain_on_channel(
477 hdd_adapter_t *pAdapter)
478{
479 VOS_STATUS status = VOS_STATUS_SUCCESS;
480 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
481 hdd_adapter_t *pAdapter_temp;
482 v_BOOL_t isGoPresent = VOS_FALSE;
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530483 hdd_context_t *pHddCtx;
484 hdd_cfg80211_state_t *cfgState;
485 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
486 rem_on_channel_request_type_t request_type;
487 int ret = 0;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530488
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530489 ENTER();
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530490 if (NULL == pAdapter)
491 {
492 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
493 "%s: Adapter is NULL",__func__);
494 return -EINVAL;
495 }
496 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
497 ret = wlan_hdd_validate_context(pHddCtx);
498 if (0 != ret)
499 {
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530500 return ret;
501 }
502 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
503 if (NULL == cfgState)
504 {
505 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
506 "%s: cfgState is not valid ",__func__);
507 return -EINVAL;
508 }
509 pRemainChanCtx = cfgState->remain_on_chan_ctx;
510 request_type = pRemainChanCtx->rem_on_chan_request;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530511 /* Initialize Remain on chan timer */
512 status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
513 VOS_TIMER_TYPE_SW,
514 wlan_hdd_remain_on_chan_timeout,
515 pAdapter);
516 if (status != VOS_STATUS_SUCCESS)
517 {
518 hddLog(VOS_TRACE_LEVEL_ERROR,
Ganesh Kondabattini02795ae2015-02-02 17:45:19 +0530519 FL("Not able to initalize remain_on_chan timer"));
520 cfgState->remain_on_chan_ctx = NULL;
521 vos_mem_free(pRemainChanCtx);
522 return -EINVAL;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530523 }
Ganesh Kondabattini02795ae2015-02-02 17:45:19 +0530524
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530525 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
526 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
527 {
528 pAdapter_temp = pAdapterNode->pAdapter;
529 if (WLAN_HDD_P2P_GO == pAdapter_temp->device_mode)
530 {
531 isGoPresent = VOS_TRUE;
532 }
533 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
534 pAdapterNode = pNext;
535 }
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530536 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530537 //call sme API to start remain on channel.
538 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
539 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
540 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
541 )
542 {
543 tANI_U8 sessionId = pAdapter->sessionId;
544 //call sme API to start remain on channel.
545 if (eHAL_STATUS_SUCCESS != sme_RemainOnChannel(
546 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
547 pRemainChanCtx->chan.hw_value, pRemainChanCtx->duration,
548 wlan_hdd_remain_on_channel_callback, pAdapter,
549 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE))
550 {
551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
552 FL(" RemainOnChannel returned fail"));
553 cfgState->remain_on_chan_ctx = NULL;
554 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
555 vos_mem_free (pRemainChanCtx);
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530556 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530557 return -EINVAL;
558 }
559
560 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
561 {
562 if( eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame(
563 WLAN_HDD_GET_HAL_CTX(pAdapter),
564 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
565 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ))
566 {
567 hddLog(VOS_TRACE_LEVEL_ERROR, "sme_RegisterMgmtFrame returned fail");
568 }
569 }
570
571 }
Abhishek Singh36b7c532015-03-13 15:50:54 +0530572 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530573 {
574 //call sme API to start remain on channel.
575 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
576 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
577 pRemainChanCtx->chan.hw_value, pRemainChanCtx->duration,
578 wlan_hdd_remain_on_channel_callback, pAdapter ))
579
580 {
581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
582 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
583 cfgState->remain_on_chan_ctx = NULL;
584 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
585 vos_mem_free (pRemainChanCtx);
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530586 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530587 return -EINVAL;
588 }
589
590
591 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
592 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
593 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
594 NULL, 0 ))
595 {
596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
597 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
598 WLANSAP_CancelRemainOnChannel(
599 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530600 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530601 return -EINVAL;
602 }
603
604 }
605
606 pAdapter->is_roc_inprogress = TRUE;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530607 EXIT();
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530608 return 0;
609}
610
611
Jeff Johnson32d95a32012-09-10 13:15:23 -0700612static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
613 struct net_device *dev,
614 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700615#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700616 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700617#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700618 unsigned int duration, u64 *cookie,
619 rem_on_channel_request_type_t request_type )
620{
621 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
622 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
623 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530624 hdd_context_t *pHddCtx = NULL;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530625 VOS_STATUS checkReadyInd;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530626 hdd_adapter_t *pStaAdapter;
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530627 int status = 0;
628
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530629 ENTER();
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530630 if (NULL == pAdapter)
631 {
632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
633 "%s: HDD adapter is Null", __func__);
634 return -ENODEV;
635 }
636
637 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
638 status = wlan_hdd_validate_context(pHddCtx);
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530639 if (0 != status)
640 {
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530641 return status;
642 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530643
Jeff Johnson32d95a32012-09-10 13:15:23 -0700644 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
645 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700646#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530647 hddLog(VOS_TRACE_LEVEL_INFO,
648 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
649 " request type %d, cookie %llu",
650 chan->hw_value, chan->center_freq, channel_type, duration,
651 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700652#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530653 hddLog(VOS_TRACE_LEVEL_INFO,
654 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
655 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
656 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700657#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700658 //Cancel existing remain On Channel if any
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530659 checkReadyInd = wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
660 if (VOS_STATUS_SUCCESS != checkReadyInd)
661 {
662 hddLog( LOGE, FL("Cancel Roc in progress"));
663 return -EBUSY;
664 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700665
Jeff Johnsone7245742012-09-05 17:12:55 -0700666 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700667 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700668 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700669 * channel requets when Load/Unload is in progress*/
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530670 if(hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx))
Jeff Johnson295189b2012-06-20 16:38:30 -0700671 {
672 hddLog( LOGE,
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530673 "%s: Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700674 return -EBUSY;
675 }
676
677 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
678 if( NULL == pRemainChanCtx )
679 {
680 hddLog(VOS_TRACE_LEVEL_FATAL,
681 "%s: Not able to allocate memory for Channel context",
682 __func__);
683 return -ENOMEM;
684 }
685
Ganesh Kondabattini8ae1a072015-02-02 17:49:50 +0530686 vos_mem_zero(pRemainChanCtx, sizeof (hdd_remain_on_chan_ctx_t));
Jeff Johnson295189b2012-06-20 16:38:30 -0700687 vos_mem_copy( &pRemainChanCtx->chan, chan,
688 sizeof(struct ieee80211_channel) );
689
Yue Maf49ba872013-08-19 12:04:25 -0700690#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700691 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700692#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700693 pRemainChanCtx->duration = duration;
694 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800695 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700696 pRemainChanCtx->cookie = *cookie;
697 pRemainChanCtx->rem_on_chan_request = request_type;
698 cfgState->remain_on_chan_ctx = pRemainChanCtx;
699 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530700 pRemainChanCtx->action_pkt_buff.freq = 0;
701 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
702 pRemainChanCtx->action_pkt_buff.frame_length = 0;
703 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530704 pRemainChanCtx->is_pending_roc_cancelled = FALSE;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530705
Jeff Johnson295189b2012-06-20 16:38:30 -0700706 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
707
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530708 if (REMAIN_ON_CHANNEL_REQUEST == request_type)
Jeff Johnson295189b2012-06-20 16:38:30 -0700709 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530710 pStaAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
711 if((NULL != pStaAdapter)&&
712 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pStaAdapter)))
Sushant Kaushik298a8592014-12-09 17:34:07 +0530713 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530714 if (pAdapter->lastRocTs !=0 &&
715 ((vos_timer_get_system_time() - pAdapter->lastRocTs )
716 < pHddCtx->cfg_ini->gP2PListenDeferInterval))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530717 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530718 if (pRemainChanCtx->duration > HDD_P2P_MAX_ROC_DURATION)
719 pRemainChanCtx->duration = HDD_P2P_MAX_ROC_DURATION;
720 schedule_delayed_work(&pAdapter->roc_work,
721 msecs_to_jiffies(pHddCtx->cfg_ini->gP2PListenDeferInterval));
722 hddLog(VOS_TRACE_LEVEL_INFO, "Defer interval is %hu, pAdapter %p",
723 pHddCtx->cfg_ini->gP2PListenDeferInterval, pAdapter);
724 return 0;
Rashmi Ramannac7744532013-10-06 16:49:08 +0530725 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800726 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700727 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530728
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530729 status = wlan_hdd_p2p_start_remain_on_channel(pAdapter);
730
731 EXIT();
732 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700733}
734
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530735int __wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800736#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
737 struct wireless_dev *wdev,
738#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700739 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800740#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700741 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700742#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700743 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700744#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700745 unsigned int duration, u64 *cookie )
746{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800747#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
748 struct net_device *dev = wdev->netdev;
749#endif
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530750 hdd_adapter_t *pAdapter;
751 hdd_context_t *pHddCtx;
752 int ret = 0;
753
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530754 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530755 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
756 if (NULL == pAdapter)
757 {
758 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
759 "%s: Adapter is NULL",__func__);
760 return -EINVAL;
761 }
762 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
763 ret = wlan_hdd_validate_context(pHddCtx);
764 if (0 != ret)
765 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530766 return ret;
767 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530768
769 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
770 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
771 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530772 ret = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700773 chan,
774#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
775 channel_type,
776#endif
777 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700778 REMAIN_ON_CHANNEL_REQUEST);
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530779 EXIT();
780 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700781}
782
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530783int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
784#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
785 struct wireless_dev *wdev,
786#else
787 struct net_device *dev,
788#endif
789 struct ieee80211_channel *chan,
790#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
791 enum nl80211_channel_type channel_type,
792#endif
793 unsigned int duration, u64 *cookie )
794{
795 int ret;
796
797 vos_ssr_protect(__func__);
798 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
799#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
800 wdev,
801#else
802 dev,
803#endif
804 chan,
805#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
806 channel_type,
807#endif
808 duration, cookie);
809 vos_ssr_unprotect(__func__);
810
811 return ret;
812}
813
814
Jeff Johnson295189b2012-06-20 16:38:30 -0700815void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
816{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530817 hdd_cfg80211_state_t *cfgState = NULL;
818 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530819 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530820 if (NULL == pAdapter)
821 {
822 hddLog(LOGE, FL("pAdapter is NULL"));
823 return;
824 }
825 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
826 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Deepthi Gowri22d08752015-02-05 15:07:40 +0530827 pAdapter->startRocTs = vos_timer_get_system_time();
Jeff Johnson295189b2012-06-20 16:38:30 -0700828 if( pRemainChanCtx != NULL )
829 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530830 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
831 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
832 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530833 //start timer for actual duration
834 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
835 (pRemainChanCtx->duration));
836 if (VOS_STATUS_SUCCESS!=status)
837 {
838 hddLog( LOGE, FL("Remain on Channel timer start failed"));
839 }
840 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700841 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800842 cfg80211_ready_on_channel(
843#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
844 pAdapter->dev->ieee80211_ptr,
845#else
846 pAdapter->dev,
847#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800848 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700849 &pRemainChanCtx->chan,
850#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
851 pRemainChanCtx->chan_type,
852#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700853 pRemainChanCtx->duration, GFP_KERNEL );
854 }
855#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530856 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700857 {
858 complete(&pAdapter->offchannel_tx_event);
859 }
860#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530861 // Check for cached action frame
862 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
863 {
Anand N Sunkad7bfc8e42015-07-29 09:59:45 +0530864#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
865 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr,
866 pRemainChanCtx->action_pkt_buff.freq, 0,
867 pRemainChanCtx->action_pkt_buff.frame_ptr,
868 pRemainChanCtx->action_pkt_buff.frame_length,
869 NL80211_RXMGMT_FLAG_ANSWERED);
870#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
Anand N Sunkade9adb1b2015-07-29 09:56:45 +0530871 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr,
872 pRemainChanCtx->action_pkt_buff.freq, 0,
873 pRemainChanCtx->action_pkt_buff.frame_ptr,
874 pRemainChanCtx->action_pkt_buff.frame_length,
875 NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
876#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530877 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
878 pRemainChanCtx->action_pkt_buff.freq, 0,
879 pRemainChanCtx->action_pkt_buff.frame_ptr,
880 pRemainChanCtx->action_pkt_buff.frame_length,
881 GFP_ATOMIC );
882#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
883 cfg80211_rx_mgmt( pAdapter->dev,
884 pRemainChanCtx->action_pkt_buff.freq, 0,
885 pRemainChanCtx->action_pkt_buff.frame_ptr,
886 pRemainChanCtx->action_pkt_buff.frame_length,
887 GFP_ATOMIC );
888#else
889 cfg80211_rx_mgmt( pAdapter->dev,
890 pRemainChanCtx->action_pkt_buff.freq,
891 pRemainChanCtx->action_pkt_buff.frame_ptr,
892 pRemainChanCtx->action_pkt_buff.frame_length,
893 GFP_ATOMIC );
894#endif //LINUX_VERSION_CODE
895 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
896 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
897 pRemainChanCtx->action_pkt_buff.frame_length = 0;
898 pRemainChanCtx->action_pkt_buff.freq = 0;
899 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
900 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530901 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
902 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700903 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530904 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
905 {
906 /* since pRemainChanCtx->is_pending_roc_cancelled is
907 * set, it means Cancel Reamain on channel command is
908 * pending because remain on channel event was not
909 * ready when cancel ROC was issued.So issue
910 * cancel ROC now.
911 */
912 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
913 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700914 }
915 else
916 {
917 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
918 }
919 return;
920}
921
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530922int __wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800923#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
924 struct wireless_dev *wdev,
925#else
926 struct net_device *dev,
927#endif
928 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -0700929{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800930#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
931 struct net_device *dev = wdev->netdev;
932#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700933 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -0700934 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530935 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530936 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
937 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530938 u64 cookie_dummy;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530939
940 ENTER();
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530941 cookie_dummy = cookie << 32;
942 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
943 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
944 pAdapter->sessionId, cookie_dummy));
945 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -0700946
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530947 status = wlan_hdd_validate_context(pHddCtx);
948
949 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700950 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530951 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -0700952 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530953 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
954
Jeff Johnson295189b2012-06-20 16:38:30 -0700955 /* FIXME cancel currently running remain on chan.
956 * Need to check cookie and cancel accordingly
957 */
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530958 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700959 if( (cfgState->remain_on_chan_ctx == NULL) ||
960 (cfgState->remain_on_chan_ctx->cookie != cookie) )
961 {
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +0530962 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700963 hddLog( LOGE,
964 "%s: No Remain on channel pending with specified cookie value",
965 __func__);
966 return -EINVAL;
967 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530968 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
969 {
Deepthi Gowri0e5c5d32015-03-30 13:52:53 +0530970 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530971 /* wait until remain on channel ready event received
972 * for already issued remain on channel request */
973 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
974 msecs_to_jiffies(WAIT_REM_CHAN_READY));
975 if (0 >= status)
976 {
977 hddLog( LOGE,
978 "%s: timeout waiting for remain on channel ready indication %d",
979 __func__, status);
Swaroop Golti05f63402015-07-22 11:59:59 +0530980 mutex_lock(&pHddCtx->roc_lock);
981 if (cfgState->remain_on_chan_ctx)
982 cfgState->remain_on_chan_ctx->is_pending_roc_cancelled = TRUE;
983 mutex_unlock(&pHddCtx->roc_lock);
984
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530985 return 0;
986
987 }
Deepthi Gowri0e5c5d32015-03-30 13:52:53 +0530988 mutex_lock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530989 }
990 else
991 {
992 hddLog( LOG1, FL("Cancel ROC event is already pending, "
993 "waiting for ready on channel indication.") );
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +0530994 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530995 return 0;
996 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530997 if (NULL != cfgState->remain_on_chan_ctx)
998 {
999 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1000 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
1001 {
Deepthi Gowri0e5c5d32015-03-30 13:52:53 +05301002 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301003 hddLog( LOG1,
1004 FL("ROC timer cancellation in progress,"
1005 " wait for completion"));
1006 status = wait_for_completion_interruptible_timeout(
1007 &pAdapter->cancel_rem_on_chan_var,
1008 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1009 if (0 >= status)
1010 {
1011 hddLog( LOGE,
1012 "%s:wait on cancel_rem_on_chan_var failed %d",
1013 __func__, status);
1014 }
1015 return 0;
1016 }
1017 else
1018 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
1019 }
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +05301020 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001021 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
1022 /* Issue abort remain on chan request to sme.
1023 * The remain on channel callback will make sure the remain_on_chan
1024 * expired event is sent.
1025 */
Abhishek Singh36b7c532015-03-13 15:50:54 +05301026 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
1027 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
Deepthi Gowri70498252015-01-20 15:56:45 +05301028 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001029 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301030 tANI_U8 sessionId = pAdapter->sessionId;
Deepthi Gowri70498252015-01-20 15:56:45 +05301031 if (eHAL_STATUS_SUCCESS !=
1032 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
1033 sessionId ))
1034 {
1035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1036 FL("Failed to Cancel Remain on Channel"));
1037 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001038 }
Deepthi Gowri70498252015-01-20 15:56:45 +05301039 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001040 {
1041 WLANSAP_CancelRemainOnChannel(
Deepthi Gowri70498252015-01-20 15:56:45 +05301042 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001043 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301044 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001045 {
1046 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
1047 __func__, pAdapter->device_mode);
1048 return -EIO;
1049 }
c_hpothu7f63e882013-10-02 19:13:35 +05301050 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -07001051 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +05301052 if (0 >= status)
1053 {
1054 hddLog( LOGE,
1055 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
1056 }
Sushant Kaushik83392fa2015-05-05 17:44:40 +05301057 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301058
1059 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07001060 return 0;
1061}
1062
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301063int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001064#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301065 struct wireless_dev *wdev,
1066#else
1067 struct net_device *dev,
1068#endif
1069 u64 cookie )
1070{
1071 int ret;
1072
1073 vos_ssr_protect(__func__);
1074 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
1075#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1076 wdev,
1077#else
1078 dev,
1079#endif
1080 cookie);
1081 vos_ssr_unprotect(__func__);
1082
1083 return ret;
1084}
1085
1086
1087#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1088int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001089 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -07001090#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001091 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -07001092 bool channel_type_valid,
1093#endif
1094 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001095 const u8 *buf, size_t len, bool no_cck,
1096 bool dont_wait_for_ack, u64 *cookie )
1097#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301098int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001099 struct ieee80211_channel *chan, bool offchan,
1100 enum nl80211_channel_type channel_type,
1101 bool channel_type_valid, unsigned int wait,
1102 const u8 *buf, size_t len, bool no_cck,
1103 bool dont_wait_for_ack, u64 *cookie )
1104#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301105int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001106 struct ieee80211_channel *chan, bool offchan,
1107 enum nl80211_channel_type channel_type,
1108 bool channel_type_valid, unsigned int wait,
1109 const u8 *buf, size_t len, u64 *cookie )
1110#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301111int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001112 struct ieee80211_channel *chan,
1113 enum nl80211_channel_type channel_type,
1114 bool channel_type_valid,
1115 const u8 *buf, size_t len, u64 *cookie )
1116#endif //LINUX_VERSION_CODE
1117{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001118#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1119 struct net_device *dev = wdev->netdev;
1120#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001121 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301122 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1123 hdd_remain_on_chan_ctx_t *pRemainChanCtx = cfgState->remain_on_chan_ctx;
1124 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -07001125 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
1126 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
Mukul Sharma1e5d0b72014-07-01 19:22:21 +05301127 tActionFrmType actionFrmType = WLAN_HDD_ACTION_FRM_TYPE_MAX;
Jeff Johnsone7245742012-09-05 17:12:55 -07001128 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301129 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -07001130
Jeff Johnson295189b2012-06-20 16:38:30 -07001131#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1132 hdd_adapter_t *goAdapter;
1133#endif
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301134
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301135 ENTER();
1136 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301137 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
1138 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301139 status = wlan_hdd_validate_context(pHddCtx);
1140
1141 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001142 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301143 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001144 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301145
c_hpothu7f63e882013-10-02 19:13:35 +05301146 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
1147 __func__, pAdapter->device_mode, type);
1148
1149
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001150 if ((type == SIR_MAC_MGMT_FRAME) &&
1151 (subType == SIR_MAC_MGMT_ACTION) &&
1152 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
1153 {
1154 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301155#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001156 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001157 {
1158 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
1159 actionFrmType);
1160 }
1161 else
1162 {
1163 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
1164 p2p_action_frame_type[actionFrmType]);
1165 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1166 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1167 {
1168 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1169 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001170 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001171 }
1172 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1173 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1174 {
1175 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1176 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
1177 " completed state");
1178 }
1179 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001180#endif
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301181 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001182
Jeff Johnsone7245742012-09-05 17:12:55 -07001183#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1184 noack = dont_wait_for_ack;
1185#endif
1186
1187 //If the wait is coming as 0 with off channel set
1188 //then set the wait to 200 ms
1189 if (offchan && !wait)
Deepthi Gowri22d08752015-02-05 15:07:40 +05301190 {
Ganesh Kondabattini7f6049c2015-02-20 20:39:05 +05301191 wait = ACTION_FRAME_DEFAULT_WAIT;
1192 if (pRemainChanCtx)
1193 {
1194 tANI_U32 current_time = vos_timer_get_system_time();
1195 int remaining_roc_time = ((int) pRemainChanCtx->duration -
1196 (current_time - pAdapter->startRocTs));
1197 if ( remaining_roc_time > ACTION_FRAME_DEFAULT_WAIT)
1198 wait = remaining_roc_time;
1199 }
Deepthi Gowri22d08752015-02-05 15:07:40 +05301200 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001201
Jeff Johnson295189b2012-06-20 16:38:30 -07001202 //Call sme API to send out a action frame.
1203 // OR can we send it directly through data path??
1204 // After tx completion send tx status back.
1205 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1206 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1207 )
1208 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001209 if (type == SIR_MAC_MGMT_FRAME)
1210 {
1211 if (subType == SIR_MAC_MGMT_PROBE_RSP)
1212 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301213 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -07001214 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301215 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001216 goto err_rem_channel;
1217 }
1218 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
1219 (subType == SIR_MAC_MGMT_DEAUTH))
1220 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001221 /* During EAP failure or P2P Group Remove supplicant
1222 * is sending del_station command to driver. From
1223 * del_station function, Driver will send deauth frame to
1224 * p2p client. No need to send disassoc frame from here.
1225 * so Drop the frame here and send tx indication back to
1226 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -07001227 */
1228 tANI_U8 dstMac[ETH_ALEN] = {0};
1229 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07001230 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001231 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -08001232 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001233 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08001234 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001235 goto err_rem_channel;
1236 }
1237 }
1238 }
1239
1240 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001241 {
1242 if ( !noack )
1243 {
1244 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1245 __func__);
1246 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1247 }
1248 else
1249 {
1250 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1251 __func__);
1252 return -EBUSY;
1253 }
1254 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001255
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301256 if( subType == SIR_MAC_MGMT_ACTION)
1257 {
1258 hddLog( LOG1, "Action frame tx request : %s",
1259 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1260 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001261
1262#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1263 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1264
1265 //If GO adapter exists and operating on same frequency
1266 //then we will not request remain on channel
1267 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1268 == goAdapter->sessionCtx.ap.operatingChannel ) )
1269 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301270 /* if GO exist and is not off channel
1271 * wait time should be zero.
1272 */
1273 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001274 goto send_frame;
1275 }
1276#endif
1277
1278#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1279 if( offchan && wait)
1280 {
1281 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301282 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001283 // In case of P2P Client mode if we are already
1284 // on the same channel then send the frame directly
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301285 mutex_lock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301286 if( (cfgState->remain_on_chan_ctx != NULL) &&
1287 (cfgState->current_freq == chan->center_freq)
1288 )
1289 {
1290 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
1291 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301292 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301293 /* Some times FW is taking almost 500 msec for
1294 * full 15 retries, which leads to ROC expiration
1295 * by the time peer gets response from other peer.
1296 * Therefore as part of temporary fix , in host
1297 * ROC time is extended. For frames where we are
1298 * expecting response from peer , its extended by
1299 * 500 msec to make ROC wait time as 1 sec and
1300 * in other cases its extended by 300 msec to make
1301 * total ROC wait as 500 msec.
1302 * TODO: FW needs to fix as why 15 retry is taking
1303 * such long time.
1304 */
1305 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1306 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1307 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1308 wait = wait + ACTION_FRAME_RSP_WAIT;
1309 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1310 actionFrmType == WLAN_HDD_INVITATION_RESP )
1311 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301312 vos_timer_stop(
1313 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1314 status = vos_timer_start(
1315 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer,
1316 wait);
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301317
1318 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301319
1320 hddLog(VOS_TRACE_LEVEL_INFO,
1321 "action frame: extending the wait time %u",
1322 wait);
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301323
1324 if ( status != VOS_STATUS_SUCCESS )
1325 {
1326 hddLog( LOGE, "Remain on Channel timer start failed");
1327 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301328 goto send_frame;
1329 }
1330 else
1331 {
1332 if ( TRUE ==
1333 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1334 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301335 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301336 hddLog(VOS_TRACE_LEVEL_INFO,
1337 "action frame tx: waiting for completion of ROC ");
1338
1339 status = wait_for_completion_interruptible_timeout(
1340 &pAdapter->cancel_rem_on_chan_var,
1341 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1342 if (0 >= status)
1343 {
1344 hddLog( LOGE,
1345 "%s:wait on cancel_rem_on_chan_var failed %d",
1346 __func__, status);
1347 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301348 goto bypass_lock;
vamsida0e5ab2013-12-26 14:33:27 +05301349 }
1350 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301351 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301352 mutex_unlock(&pHddCtx->roc_lock);
1353bypass_lock:
Rashmi Ramannac7744532013-10-06 16:49:08 +05301354 hddLog(VOS_TRACE_LEVEL_INFO,
1355 "action frame: Request ROC for wait time %u", wait);
Jeff Johnson295189b2012-06-20 16:38:30 -07001356 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001357 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001358 chan,
1359#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1360 channel_type,
1361#endif
1362 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301363 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001364
1365 if(0 != status)
1366 {
1367 if( (-EBUSY == status) &&
1368 (cfgState->current_freq == chan->center_freq) )
1369 {
1370 goto send_frame;
1371 }
1372 goto err_rem_channel;
1373 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001374 /* Wait for driver to be ready on the requested channel */
1375 status = wait_for_completion_interruptible_timeout(
1376 &pAdapter->offchannel_tx_event,
1377 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301378 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001379 {
c_hpothu7f63e882013-10-02 19:13:35 +05301380 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001381 goto err_rem_channel;
1382 }
1383 }
1384 else if ( offchan )
1385 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001386 /* Check before sending action frame
1387 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001388 if(NULL == cfgState->remain_on_chan_ctx)
1389 {
1390 goto err_rem_channel;
1391 }
1392 }
1393 send_frame:
1394#endif
1395
Jeff Johnsone7245742012-09-05 17:12:55 -07001396 if(!noack)
1397 {
1398 cfgState->buf = vos_mem_malloc( len ); //buf;
1399 if( cfgState->buf == NULL )
1400 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001401
Jeff Johnsone7245742012-09-05 17:12:55 -07001402 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001403
Jeff Johnsone7245742012-09-05 17:12:55 -07001404 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001405
1406#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001407 if( cfgState->remain_on_chan_ctx )
1408 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301409 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07001410 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1411 *cookie = cfgState->action_cookie;
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301412 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07001413 }
1414 else
1415 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001416#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001417 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001418 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001419#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001420 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001421#endif
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301422 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001423
1424 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001425 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1426 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001427 )
1428 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001429 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001430
Jeff Johnsone7245742012-09-05 17:12:55 -07001431 if ((type == SIR_MAC_MGMT_FRAME) &&
1432 (subType == SIR_MAC_MGMT_ACTION) &&
1433 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001434 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001435 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301436 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001437 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001438 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001439 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301440 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001441 }
1442 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1443 {
1444 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301445 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001446 }
1447 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301448
Jeff Johnson295189b2012-06-20 16:38:30 -07001449 if (eHAL_STATUS_SUCCESS !=
1450 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301451 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001452 {
1453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1454 "%s: sme_sendAction returned fail", __func__);
1455 goto err;
1456 }
1457 }
Abhishek Singh36b7c532015-03-13 15:50:54 +05301458 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001459 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001460 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001461 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001462 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001463 {
1464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1465 "%s: WLANSAP_SendAction returned fail", __func__);
1466 goto err;
1467 }
1468 }
1469
1470 return 0;
1471err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001472 if(!noack)
1473 {
1474 hdd_sendActionCnf( pAdapter, FALSE );
1475 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001476 return 0;
1477err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001478 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001479 cfg80211_mgmt_tx_status(
1480#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1481 pAdapter->dev->ieee80211_ptr,
1482#else
1483 pAdapter->dev,
1484#endif
1485 *cookie, buf, len, FALSE, GFP_KERNEL );
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301486 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07001487 return 0;
1488}
1489
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05301490#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
1491int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
1492 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
1493#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301494int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
1495 struct ieee80211_channel *chan, bool offchan,
1496#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1497 enum nl80211_channel_type channel_type,
1498 bool channel_type_valid,
1499#endif
1500 unsigned int wait,
1501 const u8 *buf, size_t len, bool no_cck,
1502 bool dont_wait_for_ack, u64 *cookie )
1503#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1504int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1505 struct ieee80211_channel *chan, bool offchan,
1506 enum nl80211_channel_type channel_type,
1507 bool channel_type_valid, unsigned int wait,
1508 const u8 *buf, size_t len, bool no_cck,
1509 bool dont_wait_for_ack, u64 *cookie )
1510#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1511int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1512 struct ieee80211_channel *chan, bool offchan,
1513 enum nl80211_channel_type channel_type,
1514 bool channel_type_valid, unsigned int wait,
1515 const u8 *buf, size_t len, u64 *cookie )
1516#else
1517int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1518 struct ieee80211_channel *chan,
1519 enum nl80211_channel_type channel_type,
1520 bool channel_type_valid,
1521 const u8 *buf, size_t len, u64 *cookie )
1522#endif //LINUX_VERSION_CODE
1523{
1524 int ret;
1525
1526 vos_ssr_protect(__func__);
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05301527#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
1528 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan,
1529 params->wait, params->buf, params->len,
1530 params->no_cck, params->dont_wait_for_ack,
1531 cookie);
1532#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301533 ret = __wlan_hdd_mgmt_tx(wiphy, wdev,
1534 chan, offchan,
1535#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1536 channel_type,
1537 channel_type_valid,
1538#endif
1539 wait,
1540 buf, len, no_cck,
1541 dont_wait_for_ack, cookie);
1542#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1543 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1544 channel_type, channel_type_valid, wait,
1545 buf, len, no_cck,
1546 dont_wait_for_ack, cookie);
1547#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1548 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1549 channel_type, channel_type_valid, wait,
1550 buf, len, cookie);
1551#else
1552 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, channel_type,
1553 channel_type_valid, buf, len, cookie);
1554#endif //LINUX_VERSION_CODE
1555 vos_ssr_unprotect(__func__);
1556
1557 return ret;
1558}
1559
Jeff Johnson295189b2012-06-20 16:38:30 -07001560#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001561#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301562int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001563 struct wireless_dev *wdev,
1564 u64 cookie)
1565{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301566 u64 cookie_dummy;
1567 cookie_dummy = cookie << 32;
1568 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1569 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001570 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1571}
1572#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301573int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001574 struct net_device *dev,
1575 u64 cookie)
1576{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301577 u64 cookie_dummy;
1578 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1579 cookie_dummy = cookie << 32;
1580 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1581 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1582 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001583 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1584}
1585#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001586#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001587
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301588#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1589#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1590int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1591 struct wireless_dev *wdev,
1592 u64 cookie)
1593{
1594 int ret;
1595
1596 vos_ssr_protect(__func__);
1597 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1598 vos_ssr_unprotect(__func__);
1599
1600 return ret;
1601}
1602#else
1603int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1604 struct net_device *dev,
1605 u64 cookie)
1606{
1607 int ret;
1608
1609 vos_ssr_protect(__func__);
1610 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie);
1611 vos_ssr_unprotect(__func__);
1612
1613 return ret;
1614}
1615#endif
1616#endif
1617
Jeff Johnson295189b2012-06-20 16:38:30 -07001618void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1619{
1620 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1621
Jeff Johnsone7245742012-09-05 17:12:55 -07001622 cfgState->actionFrmState = HDD_IDLE;
1623
Jeff Johnson295189b2012-06-20 16:38:30 -07001624 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1625 if( NULL == cfgState->buf )
1626 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001627 return;
1628 }
1629
1630 /* If skb is NULL it means this packet was received on CFG80211 interface
1631 * else it was received on Monitor interface */
1632 if( cfgState->skb == NULL )
1633 {
1634 /*
1635 * buf is the same pointer it passed us to send. Since we are sending
1636 * it through control path, we use different buffers.
1637 * In case of mac80211, they just push it to the skb and pass the same
1638 * data while sending tx ack status.
1639 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001640 cfg80211_mgmt_tx_status(
1641#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1642 pAdapter->dev->ieee80211_ptr,
1643#else
1644 pAdapter->dev,
1645#endif
1646 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001647 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1648 vos_mem_free( cfgState->buf );
1649 cfgState->buf = NULL;
1650 }
1651 else
1652 {
1653 hdd_adapter_t* pMonAdapter =
1654 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1655 if( pMonAdapter == NULL )
1656 {
1657 hddLog( LOGE, "Not able to get Monitor Adapter");
1658 cfgState->skb = NULL;
1659 vos_mem_free( cfgState->buf );
1660 cfgState->buf = NULL;
1661 complete(&pAdapter->tx_action_cnf_event);
1662 return;
1663 }
1664 /* Send TX completion feedback over monitor interface. */
1665 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1666 cfgState->skb = NULL;
1667 vos_mem_free( cfgState->buf );
1668 cfgState->buf = NULL;
1669 /* Look for the next Mgmt packet to TX */
1670 hdd_mon_tx_mgmt_pkt(pAdapter);
1671 }
1672 complete(&pAdapter->tx_action_cnf_event);
1673}
1674
1675/**
1676 * hdd_setP2pNoa
1677 *
1678 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301679 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001680 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1681 *
1682 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301683 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001684 *
1685 *ASSUMPTIONS:
1686 *
1687 *
1688 *NOTE:
1689 *
1690 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301691 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001692 *
1693 * @return Status
1694 */
1695
1696int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1697{
1698 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1699 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1700 VOS_STATUS status = VOS_STATUS_SUCCESS;
1701 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001702 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001703 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001704 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001705
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001706 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001707 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301708 {
1709 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1710 "%s: strnchr failed to find delimeter",__func__);
1711 return -EINVAL;
1712 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001713 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001714 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1715 if (ret < 3)
1716 {
1717 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1718 "%s: P2P_SET GO NoA: fail to read param "
1719 "count=%d duration=%d interval=%d \n",
1720 __func__, count, start_time, duration);
1721 return -EINVAL;
1722 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001724 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001725 __func__, count, start_time, duration);
1726 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001727 /* PS Selection
1728 * Periodic NoA (2)
1729 * Single NOA (4)
1730 */
1731 NoA.opp_ps = 0;
1732 NoA.ctWindow = 0;
1733 if (count == 1)
1734 {
1735 NoA.duration = 0;
1736 NoA.single_noa_duration = duration;
1737 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1738 }
1739 else
1740 {
1741 NoA.duration = duration;
1742 NoA.single_noa_duration = 0;
1743 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1744 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001745 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001746 NoA.count = count;
1747 NoA.sessionid = pAdapter->sessionId;
1748
1749 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1750 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1751 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001752 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001753 NoA.ctWindow, NoA.duration, NoA.interval,
1754 NoA.count, NoA.single_noa_duration,
1755 NoA.psSelection);
1756
1757 sme_p2pSetPs(hHal, &NoA);
1758 return status;
1759}
1760
1761/**
1762 * hdd_setP2pOpps
1763 *
1764 *FUNCTION:
1765 * This function is called from hdd_hostapd_ioctl function when Driver
1766 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1767 *
1768 *LOGIC:
1769 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1770 *
1771 *ASSUMPTIONS:
1772 *
1773 *
1774 *NOTE:
1775 *
1776 * @param dev Pointer to net device structure
1777 * @param command Pointer to command
1778 *
1779 * @return Status
1780 */
1781
1782int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1783{
1784 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1785 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1786 VOS_STATUS status = VOS_STATUS_SUCCESS;
1787 tP2pPsConfig NoA;
1788 char *param;
1789 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001790 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001791
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001792 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001793 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301794 {
1795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1796 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001797 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301798 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001799 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001800 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1801 if (ret < 3)
1802 {
1803 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1804 "%s: P2P_SET GO PS: fail to read param "
1805 " legacy_ps=%d opp_ps=%d ctwindow=%d \n",
1806 __func__, legacy_ps, opp_ps, ctwindow);
1807 return -EINVAL;
1808 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001809 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001810 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001811 __func__, legacy_ps, opp_ps, ctwindow);
1812
1813 /* PS Selection
1814 * Opportunistic Power Save (1)
1815 */
1816
1817 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1818 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301819 * values are coming from wpa_supplicant as -1.
1820 * Example : User want to set ctWindow with 30 then wpa_cli command :
1821 * P2P_SET ctwindow 30
1822 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001823 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301824 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001825 if (ctwindow != -1)
1826 {
1827
1828 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001829 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001830 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1831
1832 if (ctwindow != pAdapter->ctw)
1833 {
1834 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301835
Jeff Johnson295189b2012-06-20 16:38:30 -07001836 if(pAdapter->ops)
1837 {
1838 NoA.opp_ps = pAdapter->ops;
1839 NoA.ctWindow = pAdapter->ctw;
1840 NoA.duration = 0;
1841 NoA.single_noa_duration = 0;
1842 NoA.interval = 0;
1843 NoA.count = 0;
1844 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1845 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301846
Jeff Johnson295189b2012-06-20 16:38:30 -07001847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1848 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1849 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001850 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001851 NoA.ctWindow, NoA.duration, NoA.interval,
1852 NoA.count, NoA.single_noa_duration,
1853 NoA.psSelection);
1854
1855 sme_p2pSetPs(hHal, &NoA);
1856 }
1857 return 0;
1858 }
1859 }
1860
1861 if (opp_ps != -1)
1862 {
1863 pAdapter->ops = opp_ps;
1864
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301865 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001866 {
1867 NoA.opp_ps = opp_ps;
1868 NoA.ctWindow = pAdapter->ctw;
1869 NoA.duration = 0;
1870 NoA.single_noa_duration = 0;
1871 NoA.interval = 0;
1872 NoA.count = 0;
1873 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1874 NoA.sessionid = pAdapter->sessionId;
1875
1876 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1877 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1878 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001879 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001880 NoA.ctWindow, NoA.duration, NoA.interval,
1881 NoA.count, NoA.single_noa_duration,
1882 NoA.psSelection);
1883
1884 sme_p2pSetPs(hHal, &NoA);
1885 }
1886 }
1887 return status;
1888}
1889
1890int hdd_setP2pPs( struct net_device *dev, void *msgData )
1891{
1892 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1893 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1894 VOS_STATUS status = VOS_STATUS_SUCCESS;
1895 tP2pPsConfig NoA;
1896 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1897
1898 NoA.opp_ps = pappNoA->opp_ps;
1899 NoA.ctWindow = pappNoA->ctWindow;
1900 NoA.duration = pappNoA->duration;
1901 NoA.interval = pappNoA->interval;
1902 NoA.count = pappNoA->count;
1903 NoA.single_noa_duration = pappNoA->single_noa_duration;
1904 NoA.psSelection = pappNoA->psSelection;
1905 NoA.sessionid = pAdapter->sessionId;
1906
1907 sme_p2pSetPs(hHal, &NoA);
1908 return status;
1909}
Jeff Johnson295189b2012-06-20 16:38:30 -07001910
1911static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
1912{
1913 tANI_U8 sessionType;
1914
1915 switch( type )
1916 {
1917 case NL80211_IFTYPE_AP:
1918 sessionType = WLAN_HDD_SOFTAP;
1919 break;
1920 case NL80211_IFTYPE_P2P_GO:
1921 sessionType = WLAN_HDD_P2P_GO;
1922 break;
1923 case NL80211_IFTYPE_P2P_CLIENT:
1924 sessionType = WLAN_HDD_P2P_CLIENT;
1925 break;
1926 case NL80211_IFTYPE_STATION:
1927 sessionType = WLAN_HDD_INFRA_STATION;
1928 break;
1929 case NL80211_IFTYPE_MONITOR:
1930 sessionType = WLAN_HDD_MONITOR;
1931 break;
1932 default:
1933 sessionType = WLAN_HDD_INFRA_STATION;
1934 break;
1935 }
1936
1937 return sessionType;
1938}
1939
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001940#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301941struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001942 struct wiphy *wiphy, const char *name,
1943 enum nl80211_iftype type,
1944 u32 *flags, struct vif_params *params )
1945#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301946struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001947 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1948 u32 *flags, struct vif_params *params )
1949#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301950struct net_device* __wlan_hdd_add_virtual_intf(
Jeff Johnson295189b2012-06-20 16:38:30 -07001951 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
1952 u32 *flags, struct vif_params *params )
1953#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301954int __wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
Jeff Johnson295189b2012-06-20 16:38:30 -07001955 enum nl80211_iftype type,
1956 u32 *flags, struct vif_params *params )
1957#endif
1958{
1959 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301960 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301961 hdd_scaninfo_t *pScanInfo = NULL;
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05301962 int ret = 0;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301963
Jeff Johnson295189b2012-06-20 16:38:30 -07001964 ENTER();
1965
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05301966 ret = wlan_hdd_validate_context(pHddCtx);
1967 if (0 != ret)
1968 {
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05301969#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1970 return ERR_PTR(-EINVAL);
1971#else
1972 return -EAGAIN;
1973#endif
1974 }
1975
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301976 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1977 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05301978 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
1979 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
1980 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001981 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07001982 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001983 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05301984#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1985 return ERR_PTR(-EINVAL);
1986#else
1987 return -EAGAIN;
1988#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07001989 }
1990
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05301991 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1992 pScanInfo = &pHddCtx->scan_info;
1993 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
1994 (pHddCtx->scan_info.mScanPending))
1995 {
1996 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
1997 eCSR_SCAN_ABORT_DEFAULT);
1998 hddLog(VOS_TRACE_LEVEL_INFO,
1999 "%s: Abort Scan while adding virtual interface",__func__);
2000 }
2001
2002 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05302003 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
2004 ((NL80211_IFTYPE_P2P_GO == type) ||
2005 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07002006 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002007 /* Generate the P2P Interface Address. this address must be
2008 * different from the P2P Device Address.
2009 */
2010 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
2011 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302012 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07002013 wlan_hdd_get_session_type(type),
2014 name, p2pDeviceAddress.bytes,
2015 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07002016 }
2017 else
2018 {
2019 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
2020 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
2021 }
2022
2023 if( NULL == pAdapter)
2024 {
2025 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
2026#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05302027 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002028#else
2029 return -EINVAL;
2030#endif
2031 }
Masti, Narayanraddi41d82f02015-06-12 14:04:11 +05302032
2033 /* Below function Notifies Mode change and
2034 * If p2p session is detected then invokes functionality to
2035 * Teardown TDLS links and disable offchannel if any. Since
2036 * TDLS is not supported in case of concurrency.
2037 */
2038 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
2039
Jeff Johnson295189b2012-06-20 16:38:30 -07002040 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002041#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2042 return pAdapter->dev->ieee80211_ptr;
2043#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07002044 return pAdapter->dev;
2045#else
2046 return 0;
2047#endif
2048}
2049
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302050#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
2051struct wireless_dev* wlan_hdd_add_virtual_intf(
2052 struct wiphy *wiphy, const char *name,
2053 enum nl80211_iftype type,
2054 u32 *flags, struct vif_params *params )
2055#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2056struct wireless_dev* wlan_hdd_add_virtual_intf(
2057 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
2058 u32 *flags, struct vif_params *params )
2059#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2060struct net_device* wlan_hdd_add_virtual_intf(
2061 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
2062 u32 *flags, struct vif_params *params )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002063#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302064int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
2065 enum nl80211_iftype type,
2066 u32 *flags, struct vif_params *params )
2067#endif
2068{
2069#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)))
2070 struct wireless_dev* wdev;
2071#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2072 struct net_device* ndev;
2073#else
2074 int ret;
2075#endif
2076 vos_ssr_protect(__func__);
2077#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2078 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
2079 vos_ssr_unprotect(__func__);
2080 return wdev;
2081#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2082 ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
2083 vos_ssr_unprotect(__func__);
2084 return ndev;
2085#else
2086 ret = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
2087 vos_ssr_unprotect(__func__);
2088 return ret;
2089#endif
2090}
2091
2092#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2093int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
2094#else
2095int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002096#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002097{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002098#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2099 struct net_device *dev = wdev->netdev;
2100#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302101 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302102 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302103 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2104 int status;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302105
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302106 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07002107
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302108 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2109 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
2110 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302111 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2112 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002113
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302114 status = wlan_hdd_validate_context(pHddCtx);
2115
2116 if (0 != status)
2117 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302118 return status;
2119 }
2120
2121 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07002122 pVirtAdapter->macAddressCurrent.bytes );
2123
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05302124 hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302125 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
2126 EXIT();
2127 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002128}
2129
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302130#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2131int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
2132#else
2133int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
2134#endif
2135{
2136 int ret;
2137
2138 vos_ssr_protect(__func__);
2139#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2140 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
2141#else
2142 ret = __wlan_hdd_del_virtual_intf(wiphy, dev);
2143#endif
2144 vos_ssr_unprotect(__func__);
2145
2146 return ret;
2147}
2148
Jeff Johnson295189b2012-06-20 16:38:30 -07002149void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002150 tANI_U32 nFrameLength,
2151 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302152 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07002153{
2154 //Indicate a Frame over Monitor Intf.
2155 int rxstat;
2156 struct sk_buff *skb = NULL;
2157 int needed_headroom = 0;
2158 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
2159 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002160#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002161#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2162 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
2163#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002164#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002165 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
2166
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002167 if (NULL == pbFrames)
2168 {
2169 hddLog(LOGE, FL("NULL frame pointer"));
2170 return;
2171 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002172
2173 /* room for the radiotap header based on driver features
2174 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
2175 * RX flags.
2176 * */
2177 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
2178
2179 //alloc skb here
2180 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
2181 if (unlikely(NULL == skb))
2182 {
2183 hddLog( LOGW, FL("Unable to allocate skb"));
2184 return;
2185 }
2186 skb_reserve(skb, VPKT_SIZE_BUFFER);
2187 if (unlikely(skb_headroom(skb) < nFrameLength))
2188 {
2189 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2190 "HDD [%d]: Insufficient headroom, "
2191 "head[%p], data[%p], req[%d]",
2192 __LINE__, skb->head, skb->data, nFrameLength);
2193 kfree_skb(skb);
2194 return ;
2195 }
2196 // actually push the data
2197 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
2198 /* prepend radiotap information */
2199 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
2200 {
2201 hddLog( LOGE, FL("Not Able Add Radio Tap"));
2202 //free skb
2203 kfree_skb(skb);
2204 return ;
2205 }
2206
2207 skb_reset_mac_header( skb );
2208 skb->dev = pMonAdapter->dev;
2209 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002210 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002211#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002212#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302213 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
2214 HDD_WAKE_LOCK_DURATION,
2215 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Jeff Johnsone7245742012-09-05 17:12:55 -07002216#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002217#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002218 rxstat = netif_rx_ni(skb);
2219 if( NET_RX_SUCCESS == rxstat )
2220 {
2221 hddLog( LOG1, FL("Success"));
2222 }
2223 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302224 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07002225
2226 return ;
2227}
2228
2229void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302230 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07002231 tANI_U8* pbFrames,
2232 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05302233 tANI_U32 rxChan,
2234 tANI_S8 rxRssi )
Jeff Johnson295189b2012-06-20 16:38:30 -07002235{
2236 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302237 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07002238 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002239 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07002240 tActionFrmType actionFrmType;
2241 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302242 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05302243 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302244 VOS_STATUS status;
2245 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002246
Agarwal Ashishae800dd2015-06-24 12:44:48 +05302247 hddLog(VOS_TRACE_LEVEL_INFO, FL("Frame Type = %d Frame Length = %d"),
2248 frameType, nFrameLength);
Jeff Johnson295189b2012-06-20 16:38:30 -07002249
2250 if (NULL == pAdapter)
2251 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002252 hddLog(LOGE, FL("pAdapter is NULL"));
2253 return;
2254 }
2255
2256 if (0 == nFrameLength)
2257 {
2258 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2259 return;
2260 }
2261
2262 if (NULL == pbFrames)
2263 {
2264 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002265 return;
2266 }
2267
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002268 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2269 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2270
2271 /* Get pAdapter from Destination mac address of the frame */
2272 if ((type == SIR_MAC_MGMT_FRAME) &&
2273 (subType != SIR_MAC_MGMT_PROBE_REQ))
2274 {
2275 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
2276 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
2277 if (NULL == pAdapter)
2278 {
2279 /* Under assumtion that we don't receive any action frame
2280 * with BCST as destination we dropping action frame
2281 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08002282 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
2283 MAC_ADDRESS_STR ,
2284 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
2285 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08002286 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002287 return;
2288 }
2289 }
2290
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002291
Jeff Johnson295189b2012-06-20 16:38:30 -07002292 if (NULL == pAdapter->dev)
2293 {
2294 hddLog( LOGE, FL("pAdapter->dev is NULL"));
2295 return;
2296 }
2297
2298 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2299 {
2300 hddLog( LOGE, FL("pAdapter has invalid magic"));
2301 return;
2302 }
2303
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302304 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2305 if (NULL == pHddCtx)
2306 {
2307 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
2308 return;
2309 }
2310
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002311 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2312 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07002313 {
2314 hdd_adapter_t *pMonAdapter =
2315 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
2316
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002317 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07002318 {
2319 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
2320 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
2321 pbFrames, frameType);
2322 return;
2323 }
2324 }
2325
2326 //Channel indicated may be wrong. TODO
2327 //Indicate an action frame.
2328 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
2329 {
2330 freq = ieee80211_channel_to_frequency( rxChan,
2331 IEEE80211_BAND_2GHZ);
2332 }
2333 else
2334 {
2335 freq = ieee80211_channel_to_frequency( rxChan,
2336 IEEE80211_BAND_5GHZ);
2337 }
2338
Jeff Johnsone7245742012-09-05 17:12:55 -07002339 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302340 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302341
2342 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002343 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07002344 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002345 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
2346 {
2347 // public action frame
2348 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08002349 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 -08002350 // P2P action frames
2351 {
2352 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002353 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002354#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002355 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
2356 {
2357 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
2358 actionFrmType);
2359 }
2360 else
2361 {
2362 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
2363 p2p_action_frame_type[actionFrmType]);
2364 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
2365 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2366 {
2367 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
2368 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002369 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002370 }
2371 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
2372 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
2373 {
2374 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08002375 hddLog(LOGE,"[P2P State]GO negotiation progress to "
2376 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002377 }
2378 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
2379 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2380 {
2381 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
2382 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
2383 " completed state Autonomous GO formation");
2384 }
2385 }
2386#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302387 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
2388 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
2389 {
2390 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
2391 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
2392 actionFrmType == WLAN_HDD_INVITATION_REQ ||
2393 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
2394 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
2395 {
2396 hddLog( LOG1, "Extend RoC timer on reception of"
2397 " Action Frame");
2398 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
2399 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
2400 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
2401 else
2402 extend_time = ACTION_FRAME_DEFAULT_WAIT;
2403 if (completion_done(&pAdapter->rem_on_chan_ready_event))
2404 {
2405 vos_timer_stop(
2406 &pRemainChanCtx->hdd_remain_on_chan_timer);
2407 status = vos_timer_start(
2408 &pRemainChanCtx->hdd_remain_on_chan_timer,
2409 extend_time);
2410 if (status != VOS_STATUS_SUCCESS)
2411 {
2412 hddLog( LOGE, "ROC timer start failed");
2413 }
2414 }
2415 else
2416 {
2417 // Buffer Packet
2418 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2419 {
2420 pRemainChanCtx->action_pkt_buff.frame_length =
2421 nFrameLength;
2422 pRemainChanCtx->action_pkt_buff.freq = freq;
2423 pRemainChanCtx->action_pkt_buff.frame_ptr
2424 = vos_mem_malloc(nFrameLength);
2425 vos_mem_copy(
2426 pRemainChanCtx->action_pkt_buff.frame_ptr,
2427 pbFrames, nFrameLength);
2428 hddLog( LOGE,"%s:"
2429 "Action Pkt Cached successfully !!!", __func__);
2430 }
2431 else
2432 {
2433 hddLog( LOGE,"%s:"
2434 "Frames are pending. dropping frame !!!",
2435 __func__);
2436 }
2437 return;
2438 }
2439 }
2440 }
2441 if (pRemainChanCtx != NULL &&
2442 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2443 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2444 hddLog( LOG1, "%s:"
2445 "Rcvd action frame after timer expired ", __func__);
2446
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302447 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2448 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2449 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2450 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2451 {
2452 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
2453 __func__);
2454 hdd_sendActionCnf(pAdapter, TRUE);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002455 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002456 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002457#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002458 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 -07002459 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002460 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302461 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002462 MAC_ADDR_ARRAY(mac),rxRssi);
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302463
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002464 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2465 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002466 }
2467#endif
2468 }
Kaushik, Sushant507a8612014-10-21 17:00:55 +05302469
2470 pScanInfo = &pHddCtx->scan_info;
2471 if ((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2472 {
2473 hddLog(LOGE,"Action frame received when Scanning is in"
2474 " progress. Abort Scan.");
2475 hdd_abort_mac_scan(pAdapter->pHddCtx,
2476 pScanInfo->sessionId,
2477 eCSR_SCAN_ABORT_DEFAULT);
2478 }
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302479
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002480 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2481 {
2482 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2483 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2484 {
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302485 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] Action type[%d] <--- OTA",
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002486 actionFrmType);
2487 }
2488 else
2489 {
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302490 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] %s <--- OTA",
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002491 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002492 }
2493 }
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302494
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002495 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2496 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2497 {
Kumar Anand82c009f2014-05-29 00:29:42 -07002498 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
2499 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002500 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002501 }
2502
Jeff Johnson295189b2012-06-20 16:38:30 -07002503 //Indicate Frame Over Normal Interface
2504 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
Anand N Sunkad7bfc8e42015-07-29 09:59:45 +05302505#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
2506 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames,
2507 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED);
2508#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05302509 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames,
2510 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
2511#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002512 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2513 pbFrames, nFrameLength,
2514 GFP_ATOMIC );
2515#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002516 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2517 pbFrames, nFrameLength,
2518 GFP_ATOMIC );
2519#else
2520 cfg80211_rx_mgmt( pAdapter->dev, freq,
2521 pbFrames, nFrameLength,
2522 GFP_ATOMIC );
2523#endif //LINUX_VERSION_CODE
2524}
2525
2526/*
2527 * ieee80211_add_rx_radiotap_header - add radiotap header
2528 */
2529static int hdd_wlan_add_rx_radiotap_hdr (
2530 struct sk_buff *skb, int rtap_len, int flag )
2531{
2532 u8 rtap_temp[20] = {0};
2533 struct ieee80211_radiotap_header *rthdr;
2534 unsigned char *pos;
2535 u16 rx_flags = 0;
2536
2537 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2538
2539 /* radiotap header, set always present flags */
2540 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2541 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2542 rthdr->it_len = cpu_to_le16(rtap_len);
2543
2544 pos = (unsigned char *) (rthdr + 1);
2545
2546 /* the order of the following fields is important */
2547
2548 /* IEEE80211_RADIOTAP_FLAGS */
2549 *pos = 0;
2550 pos++;
2551
2552 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2553 /* ensure 2 byte alignment for the 2 byte field as required */
2554 if ((pos - (u8 *)rthdr) & 1)
2555 pos++;
2556 put_unaligned_le16(rx_flags, pos);
2557 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302558
Jeff Johnson295189b2012-06-20 16:38:30 -07002559 // actually push the data
2560 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2561
2562 return 0;
2563}
2564
2565static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2566 hdd_cfg80211_state_t* cfgState,
2567 tANI_BOOLEAN actionSendSuccess )
2568{
2569 struct ieee80211_radiotap_header *rthdr;
2570 unsigned char *pos;
2571 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002572#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002573#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2574 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2575#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002576#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002577
2578 /* 2 Byte for TX flags and 1 Byte for Retry count */
2579 u32 rtHdrLen = sizeof(*rthdr) + 3;
2580
2581 u8 *data;
2582
2583 /* We have to return skb with Data starting with MAC header. We have
2584 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2585 * entire skb->len from skb and then we will push cfgState->buf to skb
2586 * */
2587 if( NULL == skb_pull(skb, skb->len) )
2588 {
2589 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2590 kfree_skb(cfgState->skb);
2591 return;
2592 }
2593
2594 data = skb_push( skb, cfgState->len );
2595
2596 if (data == NULL)
2597 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002598 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002599 kfree_skb( cfgState->skb );
2600 return;
2601 }
2602
2603 memcpy( data, cfgState->buf, cfgState->len );
2604
2605 /* send frame to monitor interfaces now */
2606 if( skb_headroom(skb) < rtHdrLen )
2607 {
2608 hddLog( LOGE, FL("No headroom for rtap header"));
2609 kfree_skb(cfgState->skb);
2610 return;
2611 }
2612
2613 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2614
2615 memset( rthdr, 0, rtHdrLen );
2616 rthdr->it_len = cpu_to_le16( rtHdrLen );
2617 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2618 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2619 );
2620
2621 pos = (unsigned char *)( rthdr+1 );
2622
2623 // Fill TX flags
2624 *pos = actionSendSuccess;
2625 pos += 2;
2626
2627 // Fill retry count
2628 *pos = 0;
2629 pos++;
2630
2631 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002632 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002633 skb->pkt_type = PACKET_OTHERHOST;
2634 skb->protocol = htons(ETH_P_802_2);
2635 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002636#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002637#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302638 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
2639 HDD_WAKE_LOCK_DURATION,
2640 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Jeff Johnsone7245742012-09-05 17:12:55 -07002641#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002642#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002643 if (in_interrupt())
2644 netif_rx( skb );
2645 else
2646 netif_rx_ni( skb );
2647
2648 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05302649 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302650 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002651
2652}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302653
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +05302654void __hdd_p2p_roc_work_queue(struct work_struct *work)
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05302655{
2656 hdd_adapter_t *pAdapter = container_of(to_delayed_work(work), hdd_adapter_t, roc_work);
2657 hddLog( VOS_TRACE_LEVEL_INFO, FL("%s: "), __func__);
2658 wlan_hdd_p2p_start_remain_on_channel(pAdapter);
2659 return;
2660}
2661
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +05302662void hdd_p2p_roc_work_queue(struct work_struct *work)
2663{
2664 vos_ssr_protect(__func__);
2665 __hdd_p2p_roc_work_queue(work);
2666 vos_ssr_unprotect(__func__);
2667 return;
2668}