blob: a60a6f225fcce671ab49344bbfc20e41359b9750 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +05302 * Copyright (c) 2012-2016, 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 );
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530176 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530177 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530178 rem_on_channel_request_type_t req_type;
179
Jeff Johnson295189b2012-06-20 16:38:30 -0700180
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530181 if (pHddCtx == NULL)
182 {
183 hddLog(LOGE, "%s: Hdd Context is NULL", __func__);
184 return eHAL_STATUS_FAILURE;
185 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530186
187 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530188
189 pRemainChanCtx = cfgState->remain_on_chan_ctx;
190 if (pRemainChanCtx == NULL)
191 {
192 hddLog( LOGW,
193 "%s: No Rem on channel pending for which Rsp is received", __func__);
194 mutex_unlock(&pHddCtx->roc_lock);
195 return eHAL_STATUS_SUCCESS;
196 }
197
Rashmi Ramannac7744532013-10-06 16:49:08 +0530198 hddLog( VOS_TRACE_LEVEL_INFO,
199 "Received ROC rsp (request type %d, channel %d, cookie %llu",
200 pRemainChanCtx->rem_on_chan_request,
201 pRemainChanCtx->chan.center_freq,
202 pRemainChanCtx->cookie);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530203 vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
204 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
205 if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
Jeff Johnson295189b2012-06-20 16:38:30 -0700206 {
207 if( cfgState->buf )
208 {
Agrawal Ashishb10d0392015-08-06 16:18:20 +0530209 hddLog( LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -0700210 "%s: We need to receive yet an ack from one of tx packet",
211 __func__);
212 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800213 cfg80211_remain_on_channel_expired(
214#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
215 pRemainChanCtx->dev->ieee80211_ptr,
216#else
217 pRemainChanCtx->dev,
218#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700219 pRemainChanCtx->cookie,
220 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700221#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
222 pRemainChanCtx->chan_type,
223#endif
224 GFP_KERNEL);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530225 pAdapter->lastRocTs = vos_timer_get_system_time();
Jeff Johnson295189b2012-06-20 16:38:30 -0700226 }
227
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530228 req_type = pRemainChanCtx->rem_on_chan_request;
229 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700230
231 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700232 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
233 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700234 )
235 {
236 tANI_U8 sessionId = pAdapter->sessionId;
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530237 if( REMAIN_ON_CHANNEL_REQUEST == req_type )
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800238 {
239 sme_DeregisterMgmtFrame(
240 hHal, sessionId,
241 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
242 NULL, 0 );
243 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700244 }
Abhishek Singh36b7c532015-03-13 15:50:54 +0530245 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -0700246 {
247 WLANSAP_DeRegisterMgmtFrame(
248 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
249 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
250 NULL, 0 );
251 }
Deepthi Gowri200d15a2015-08-10 16:02:49 +0530252 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530253 if ( pRemainChanCtx )
254 {
255 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
256 && pRemainChanCtx->action_pkt_buff.frame_length != 0)
257 {
258 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
259 }
260 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800261 vos_mem_free( pRemainChanCtx );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -0800262 pRemainChanCtx = NULL;
Ratheesh S P8278de82015-07-10 18:44:21 +0530263 cfgState->remain_on_chan_ctx = NULL;
Deepthi Gowri200d15a2015-08-10 16:02:49 +0530264 mutex_unlock(&pHddCtx->roc_lock);
Deepthi Gowri3e672f02015-01-30 17:04:08 +0530265 if (eHAL_STATUS_SUCCESS != status)
266 complete(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -0700267 complete(&pAdapter->cancel_rem_on_chan_var);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530268 pAdapter->is_roc_inprogress = FALSE;
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530269 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 return eHAL_STATUS_SUCCESS;
271}
272
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530273VOS_STATUS wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700274{
Jeff Johnson295189b2012-06-20 16:38:30 -0700275 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri7374e282015-08-26 19:22:58 +0530276 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530277 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700279
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530280 if (NULL == pHddCtx)
281 {
282 hddLog(LOGE, "%s: HddCtx is NULL", __func__);
283 return VOS_STATUS_E_FAILURE;
284 }
285
286 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri7374e282015-08-26 19:22:58 +0530287 pRemainChanCtx = cfgState->remain_on_chan_ctx;
288 if(pRemainChanCtx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700289 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530290 if(VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
Deepthi Gowri7374e282015-08-26 19:22:58 +0530291 &pRemainChanCtx->hdd_remain_on_chan_timer))
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530292 {
293 hddLog(VOS_TRACE_LEVEL_INFO,
294 "Cancel Existing ROC (cookie=%llu)",
Deepthi Gowri7374e282015-08-26 19:22:58 +0530295 pRemainChanCtx->cookie);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700296
Deepthi Gowri7374e282015-08-26 19:22:58 +0530297 vos_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530298 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530299 /* Wait till remain on channel ready indication before issuing cancel
300 * remain on channel request, otherwise if remain on channel not
301 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700302 * will be in unknown state.
303 */
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530304 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress != TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700305 {
Deepthi Gowrief88a5f2015-04-06 14:41:46 +0530306 mutex_unlock(&pHddCtx->roc_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530307 status = wait_for_completion_interruptible_timeout(
308 &pAdapter->rem_on_chan_ready_event,
309 msecs_to_jiffies(WAIT_REM_CHAN_READY));
310 if (0 >= status)
311 {
Deepthi Gowri7374e282015-08-26 19:22:58 +0530312 mutex_lock(&pHddCtx->roc_lock);
313 pRemainChanCtx = cfgState->remain_on_chan_ctx;
314 if (pRemainChanCtx)
315 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
316 mutex_unlock(&pHddCtx->roc_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530317 hddLog( LOGE,
Deepthi Gowri7374e282015-08-26 19:22:58 +0530318 "%s: timeout waiting for remain on channel"
319 " ready indication %d",
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530320 __func__, status);
Abhishek Singh837adf22015-10-01 17:37:37 +0530321 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
322 WLAN_LOG_INDICATOR_HOST_DRIVER,
323 WLAN_LOG_REASON_HDD_TIME_OUT,
324 FALSE, TRUE);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530325 return VOS_STATUS_E_FAILURE;
326 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700327
Deepthi Gowrief88a5f2015-04-06 14:41:46 +0530328 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri7374e282015-08-26 19:22:58 +0530329 pRemainChanCtx = cfgState->remain_on_chan_ctx;
330 if (NULL == pRemainChanCtx)
331 {
332 mutex_unlock(&pHddCtx->roc_lock);
333 hddLog( LOGE,
334 "%s-%d: pRemainChanCtx is NULL",
335 __func__, __LINE__);
336 return VOS_STATUS_E_FAILURE;
337 }
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530338 /* Check again if cancel remain on channel is started.
339 * If its started wait for its completiona and return.
340 */
341 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
342 {
343 mutex_unlock(&pHddCtx->roc_lock);
344 hddLog( LOG1,
345 "ROC timer cancellation in progress,"
346 " wait for completion");
347 status = wait_for_completion_interruptible_timeout(
348 &pAdapter->cancel_rem_on_chan_var,
349 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
350 if (0 >= status)
351 {
352 hddLog( LOGE,
353 "%s:wait on cancel_rem_on_chan_var failed %d",
354 __func__, status);
355 return VOS_STATUS_E_FAILURE;
356 }
357 return VOS_STATUS_SUCCESS;
358 }
359 else
360 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530361 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Abhishek Singh4892e962015-12-30 11:18:58 +0530362 mutex_unlock(&pHddCtx->roc_lock);
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530363
364 /* Issue abort remain on chan request to sme.
365 * The remain on channel callback will make sure the remain_on_chan
366 * expired event is sent.
367 */
368 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Abhishek Singh36b7c532015-03-13 15:50:54 +0530369 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
370 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ))
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530371 {
372 if (eHAL_STATUS_SUCCESS !=
373 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
Deepthi Gowri70498252015-01-20 15:56:45 +0530374 pAdapter->sessionId ))
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530375 {
376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
377 FL("Failed to Cancel Remain on Channel"));
378 }
379 }
380 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
381 {
382 WLANSAP_CancelRemainOnChannel(
383 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
384 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700385
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530386 status = wait_for_completion_interruptible_timeout(
387 &pAdapter->cancel_rem_on_chan_var,
388 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
389 if (0 >= status)
390 {
391 hddLog( LOGE,
392 "%s: timeout waiting for cancel remain on channel"
393 " ready indication %d",
394 __func__, status);
395 }
396 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530397 }
398 else
399 {
400 hddLog( LOG1,
401 "ROC timer cancellation in progress,"
402 " wait for completion");
403 mutex_unlock(&pHddCtx->roc_lock);
404 status = wait_for_completion_interruptible_timeout(
405 &pAdapter->cancel_rem_on_chan_var,
406 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
407 if (0 >= status)
408 {
409 hddLog( LOGE,
410 "%s:wait on cancel_rem_on_chan_var failed %d",
411 __func__, status);
412 return VOS_STATUS_E_FAILURE;
413 }
414 return VOS_STATUS_SUCCESS;
415 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700416 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530417 else
418 {
419 hddLog(LOG1,
420 "%s: remain_on_chan_ctx is NULL", __func__);
421 mutex_unlock(&pHddCtx->roc_lock);
422 }
423 return VOS_STATUS_SUCCESS;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700424}
425
426int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
427{
428 int status = 0;
429 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
430
431 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
432 {
433 //Cancel Existing Remain On Channel
434 //If no action frame is pending
435 if( cfgState->remain_on_chan_ctx != NULL)
436 {
437 //Check whether Action Frame is pending or not
438 if( cfgState->buf == NULL)
439 {
440 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
441 }
442 else
443 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530444 hddLog(VOS_TRACE_LEVEL_DEBUG,
445 "Cannot Cancel Existing Remain on Channel");
Jeff Johnson32d95a32012-09-10 13:15:23 -0700446 status = -EBUSY;
447 }
448 }
449 }
450 return status;
451}
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530452void wlan_hdd_remain_on_chan_timeout(void *data)
453{
454 hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530455 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530456 hdd_cfg80211_state_t *cfgState;
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530457 hdd_context_t *pHddCtx;
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +0530458
459 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530460 {
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +0530461 hddLog( LOGE, FL("pAdapter is invalid %p !!!"), pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530462 return;
463 }
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530464 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530465 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530466 mutex_lock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530467 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530468
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530469 if (NULL == pRemainChanCtx)
470 {
471 hddLog( LOGE, FL("No Remain on channel is pending"));
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530472 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530473 return;
474 }
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530475
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530476 if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
477 {
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530478 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530479 hddLog( LOGE, FL("Cancellation already in progress"));
480 return;
481 }
482
483 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
484 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Abhishek Singh4892e962015-12-30 11:18:58 +0530485 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530486 hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
Abhishek Singh36b7c532015-03-13 15:50:54 +0530487 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
488 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530489 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
490 )
491 {
Deepthi Gowri70498252015-01-20 15:56:45 +0530492 if (eHAL_STATUS_SUCCESS !=
493 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
494 pAdapter->sessionId ))
495 {
496 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
497 FL("Failed to Cancel Remain on Channel"));
498 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530499 }
Abhishek Singh36b7c532015-03-13 15:50:54 +0530500 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530501 {
Deepthi Gowri70498252015-01-20 15:56:45 +0530502 WLANSAP_CancelRemainOnChannel(
503 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530504 }
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +0530505
506 wlan_hdd_start_stop_tdls_source_timer(pHddCtx, eTDLS_SUPPORT_ENABLED);
507
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530508 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530509}
Jeff Johnson32d95a32012-09-10 13:15:23 -0700510
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530511static int wlan_hdd_p2p_start_remain_on_channel(
512 hdd_adapter_t *pAdapter)
513{
514 VOS_STATUS status = VOS_STATUS_SUCCESS;
515 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
516 hdd_adapter_t *pAdapter_temp;
517 v_BOOL_t isGoPresent = VOS_FALSE;
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530518 hdd_context_t *pHddCtx;
519 hdd_cfg80211_state_t *cfgState;
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530520 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530521 rem_on_channel_request_type_t request_type;
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530522 unsigned int duration;
523 v_U16_t hw_value;
524
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530525 int ret = 0;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530526
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530527 ENTER();
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530528 if (NULL == pAdapter)
529 {
530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
531 "%s: Adapter is NULL",__func__);
532 return -EINVAL;
533 }
534 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
535 ret = wlan_hdd_validate_context(pHddCtx);
536 if (0 != ret)
537 {
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530538 return ret;
539 }
540 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
541 if (NULL == cfgState)
542 {
543 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
544 "%s: cfgState is not valid ",__func__);
545 return -EINVAL;
546 }
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530547 mutex_lock(&pHddCtx->roc_lock);
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530548 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530549 if ( pRemainChanCtx == NULL)
550 {
551 mutex_unlock(&pHddCtx->roc_lock);
552 hddLog( LOGE,
553 "%s-%d: pRemainChanCtx is NULL",
554 __func__, __LINE__);
555 return ret;
556 }
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530557 request_type = pRemainChanCtx->rem_on_chan_request;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530558 /* Initialize Remain on chan timer */
559 status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
560 VOS_TIMER_TYPE_SW,
561 wlan_hdd_remain_on_chan_timeout,
562 pAdapter);
563 if (status != VOS_STATUS_SUCCESS)
564 {
565 hddLog(VOS_TRACE_LEVEL_ERROR,
Ganesh Kondabattini02795ae2015-02-02 17:45:19 +0530566 FL("Not able to initalize remain_on_chan timer"));
567 cfgState->remain_on_chan_ctx = NULL;
568 vos_mem_free(pRemainChanCtx);
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530569 mutex_unlock(&pHddCtx->roc_lock);
Ganesh Kondabattini02795ae2015-02-02 17:45:19 +0530570 return -EINVAL;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530571 }
Ganesh Kondabattini02795ae2015-02-02 17:45:19 +0530572
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530573 duration = pRemainChanCtx->duration;
574 hw_value = pRemainChanCtx->chan.hw_value;
575 mutex_unlock(&pHddCtx->roc_lock);
576
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530577 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
578 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
579 {
580 pAdapter_temp = pAdapterNode->pAdapter;
581 if (WLAN_HDD_P2P_GO == pAdapter_temp->device_mode)
582 {
583 isGoPresent = VOS_TRUE;
584 }
585 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
586 pAdapterNode = pNext;
587 }
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530588 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530589 //call sme API to start remain on channel.
590 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
591 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
592 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
593 )
594 {
595 tANI_U8 sessionId = pAdapter->sessionId;
596 //call sme API to start remain on channel.
597 if (eHAL_STATUS_SUCCESS != sme_RemainOnChannel(
598 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530599 hw_value, duration,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530600 wlan_hdd_remain_on_channel_callback, pAdapter,
601 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE))
602 {
603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
604 FL(" RemainOnChannel returned fail"));
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530605
606 mutex_lock(&pHddCtx->roc_lock);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530607 cfgState->remain_on_chan_ctx = NULL;
608 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
609 vos_mem_free (pRemainChanCtx);
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530610 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530611 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530612 return -EINVAL;
613 }
614
615 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
616 {
617 if( eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame(
618 WLAN_HDD_GET_HAL_CTX(pAdapter),
619 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
620 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ))
621 {
622 hddLog(VOS_TRACE_LEVEL_ERROR, "sme_RegisterMgmtFrame returned fail");
623 }
624 }
625
626 }
Abhishek Singh36b7c532015-03-13 15:50:54 +0530627 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530628 {
629 //call sme API to start remain on channel.
630 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
631 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530632 hw_value, duration,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530633 wlan_hdd_remain_on_channel_callback, pAdapter ))
634
635 {
636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
637 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530638 mutex_lock(&pHddCtx->roc_lock);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530639 cfgState->remain_on_chan_ctx = NULL;
640 vos_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
641 vos_mem_free (pRemainChanCtx);
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530642 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530643 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530644 return -EINVAL;
645 }
646
647
648 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
649 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
650 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
651 NULL, 0 ))
652 {
653 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
654 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
655 WLANSAP_CancelRemainOnChannel(
656 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530657 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530658 return -EINVAL;
659 }
660
661 }
662
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +0530663 wlan_hdd_start_stop_tdls_source_timer(pHddCtx, eTDLS_SUPPORT_DISABLED);
664
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530665 pAdapter->is_roc_inprogress = TRUE;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530666 EXIT();
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530667 return 0;
668}
669
670
Jeff Johnson32d95a32012-09-10 13:15:23 -0700671static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
672 struct net_device *dev,
673 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700674#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700675 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700676#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700677 unsigned int duration, u64 *cookie,
678 rem_on_channel_request_type_t request_type )
679{
680 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
681 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
682 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530683 hdd_context_t *pHddCtx = NULL;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530684 VOS_STATUS checkReadyInd;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530685 hdd_adapter_t *pStaAdapter;
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530686 int status = 0;
687
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530688 ENTER();
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530689 if (NULL == pAdapter)
690 {
691 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
692 "%s: HDD adapter is Null", __func__);
693 return -ENODEV;
694 }
695
696 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
697 status = wlan_hdd_validate_context(pHddCtx);
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530698 if (0 != status)
699 {
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530700 return status;
701 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530702
Jeff Johnson32d95a32012-09-10 13:15:23 -0700703 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
704 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700705#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530706 hddLog(VOS_TRACE_LEVEL_INFO,
707 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
708 " request type %d, cookie %llu",
709 chan->hw_value, chan->center_freq, channel_type, duration,
710 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700711#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530712 hddLog(VOS_TRACE_LEVEL_INFO,
713 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
714 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
715 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700716#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700717 //Cancel existing remain On Channel if any
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530718 checkReadyInd = wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
719 if (VOS_STATUS_SUCCESS != checkReadyInd)
720 {
721 hddLog( LOGE, FL("Cancel Roc in progress"));
722 return -EBUSY;
723 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700724
Jeff Johnsone7245742012-09-05 17:12:55 -0700725 /* When P2P-GO and if we are trying to unload the driver then
Jeff Johnson295189b2012-06-20 16:38:30 -0700726 * wlan driver is keep on receiving the remain on channel command
Jeff Johnsone7245742012-09-05 17:12:55 -0700727 * and which is resulting in crash. So not allowing any remain on
Jeff Johnson295189b2012-06-20 16:38:30 -0700728 * channel requets when Load/Unload is in progress*/
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530729 if(hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx))
Jeff Johnson295189b2012-06-20 16:38:30 -0700730 {
731 hddLog( LOGE,
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530732 "%s: Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700733 return -EBUSY;
734 }
735
Ganesh Kondabattinibdb415e2015-09-16 12:37:14 +0530736 mutex_lock(&pHddCtx->roc_lock);
737
Jeff Johnson295189b2012-06-20 16:38:30 -0700738 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
739 if( NULL == pRemainChanCtx )
740 {
741 hddLog(VOS_TRACE_LEVEL_FATAL,
742 "%s: Not able to allocate memory for Channel context",
743 __func__);
Ganesh Kondabattinibdb415e2015-09-16 12:37:14 +0530744 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700745 return -ENOMEM;
746 }
747
Ganesh Kondabattini8ae1a072015-02-02 17:49:50 +0530748 vos_mem_zero(pRemainChanCtx, sizeof (hdd_remain_on_chan_ctx_t));
Jeff Johnson295189b2012-06-20 16:38:30 -0700749 vos_mem_copy( &pRemainChanCtx->chan, chan,
750 sizeof(struct ieee80211_channel) );
751
Yue Maf49ba872013-08-19 12:04:25 -0700752#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700753 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700754#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700755 pRemainChanCtx->duration = duration;
756 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800757 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700758 pRemainChanCtx->cookie = *cookie;
759 pRemainChanCtx->rem_on_chan_request = request_type;
760 cfgState->remain_on_chan_ctx = pRemainChanCtx;
761 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530762 pRemainChanCtx->action_pkt_buff.freq = 0;
763 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
764 pRemainChanCtx->action_pkt_buff.frame_length = 0;
765 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530766 pRemainChanCtx->is_pending_roc_cancelled = FALSE;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530767
Jeff Johnson295189b2012-06-20 16:38:30 -0700768 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
769
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530770 if (REMAIN_ON_CHANNEL_REQUEST == request_type)
Jeff Johnson295189b2012-06-20 16:38:30 -0700771 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530772 pStaAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
773 if((NULL != pStaAdapter)&&
774 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pStaAdapter)))
Sushant Kaushik298a8592014-12-09 17:34:07 +0530775 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530776 if (pAdapter->lastRocTs !=0 &&
777 ((vos_timer_get_system_time() - pAdapter->lastRocTs )
778 < pHddCtx->cfg_ini->gP2PListenDeferInterval))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530779 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530780 if (pRemainChanCtx->duration > HDD_P2P_MAX_ROC_DURATION)
781 pRemainChanCtx->duration = HDD_P2P_MAX_ROC_DURATION;
Ganesh Kondabattinibdb415e2015-09-16 12:37:14 +0530782
783 mutex_unlock(&pHddCtx->roc_lock);
784
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530785 schedule_delayed_work(&pAdapter->roc_work,
786 msecs_to_jiffies(pHddCtx->cfg_ini->gP2PListenDeferInterval));
787 hddLog(VOS_TRACE_LEVEL_INFO, "Defer interval is %hu, pAdapter %p",
788 pHddCtx->cfg_ini->gP2PListenDeferInterval, pAdapter);
789 return 0;
Rashmi Ramannac7744532013-10-06 16:49:08 +0530790 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800791 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700792 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530793
Ganesh Kondabattinibdb415e2015-09-16 12:37:14 +0530794 mutex_unlock(&pHddCtx->roc_lock);
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530795 status = wlan_hdd_p2p_start_remain_on_channel(pAdapter);
796
797 EXIT();
798 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700799}
800
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530801int __wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800802#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
803 struct wireless_dev *wdev,
804#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700805 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800806#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700807 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700808#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700809 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700810#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700811 unsigned int duration, u64 *cookie )
812{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800813#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
814 struct net_device *dev = wdev->netdev;
815#endif
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530816 hdd_adapter_t *pAdapter;
817 hdd_context_t *pHddCtx;
818 int ret = 0;
819
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530820 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530821 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
822 if (NULL == pAdapter)
823 {
824 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
825 "%s: Adapter is NULL",__func__);
826 return -EINVAL;
827 }
828 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
829 ret = wlan_hdd_validate_context(pHddCtx);
830 if (0 != ret)
831 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530832 return ret;
833 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530834
835 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
836 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
837 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530838 ret = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700839 chan,
840#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
841 channel_type,
842#endif
843 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700844 REMAIN_ON_CHANNEL_REQUEST);
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530845 EXIT();
846 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700847}
848
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530849int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
850#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
851 struct wireless_dev *wdev,
852#else
853 struct net_device *dev,
854#endif
855 struct ieee80211_channel *chan,
856#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
857 enum nl80211_channel_type channel_type,
858#endif
859 unsigned int duration, u64 *cookie )
860{
861 int ret;
862
863 vos_ssr_protect(__func__);
864 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
865#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
866 wdev,
867#else
868 dev,
869#endif
870 chan,
871#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
872 channel_type,
873#endif
874 duration, cookie);
875 vos_ssr_unprotect(__func__);
876
877 return ret;
878}
879
880
Jeff Johnson295189b2012-06-20 16:38:30 -0700881void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
882{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530883 hdd_cfg80211_state_t *cfgState = NULL;
884 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Deepthi Gowri3124dcd2015-08-28 19:34:27 +0530885 hdd_context_t *pHddCtx;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530886 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530887 if (NULL == pAdapter)
888 {
889 hddLog(LOGE, FL("pAdapter is NULL"));
890 return;
891 }
Deepthi Gowri3124dcd2015-08-28 19:34:27 +0530892 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
893 if (NULL == pHddCtx)
894 {
895 hddLog(LOGE, FL("pHddCtx is NULL"));
896 return;
897 }
Kaushik, Sushant26402612014-05-03 16:56:06 +0530898 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri22d08752015-02-05 15:07:40 +0530899 pAdapter->startRocTs = vos_timer_get_system_time();
Deepthi Gowri3124dcd2015-08-28 19:34:27 +0530900 mutex_lock(&pHddCtx->roc_lock);
901 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700902 if( pRemainChanCtx != NULL )
903 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530904 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
905 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
906 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530907 //start timer for actual duration
908 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
909 (pRemainChanCtx->duration));
910 if (VOS_STATUS_SUCCESS!=status)
911 {
912 hddLog( LOGE, FL("Remain on Channel timer start failed"));
913 }
914 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700915 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800916 cfg80211_ready_on_channel(
917#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
918 pAdapter->dev->ieee80211_ptr,
919#else
920 pAdapter->dev,
921#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800922 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700923 &pRemainChanCtx->chan,
924#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
925 pRemainChanCtx->chan_type,
926#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700927 pRemainChanCtx->duration, GFP_KERNEL );
928 }
929#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530930 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700931 {
932 complete(&pAdapter->offchannel_tx_event);
933 }
934#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530935 // Check for cached action frame
936 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
937 {
Anand N Sunkad7bfc8e42015-07-29 09:59:45 +0530938#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
939 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr,
940 pRemainChanCtx->action_pkt_buff.freq, 0,
941 pRemainChanCtx->action_pkt_buff.frame_ptr,
942 pRemainChanCtx->action_pkt_buff.frame_length,
943 NL80211_RXMGMT_FLAG_ANSWERED);
944#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
Anand N Sunkade9adb1b2015-07-29 09:56:45 +0530945 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr,
946 pRemainChanCtx->action_pkt_buff.freq, 0,
947 pRemainChanCtx->action_pkt_buff.frame_ptr,
948 pRemainChanCtx->action_pkt_buff.frame_length,
949 NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
950#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530951 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
952 pRemainChanCtx->action_pkt_buff.freq, 0,
953 pRemainChanCtx->action_pkt_buff.frame_ptr,
954 pRemainChanCtx->action_pkt_buff.frame_length,
955 GFP_ATOMIC );
956#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
957 cfg80211_rx_mgmt( pAdapter->dev,
958 pRemainChanCtx->action_pkt_buff.freq, 0,
959 pRemainChanCtx->action_pkt_buff.frame_ptr,
960 pRemainChanCtx->action_pkt_buff.frame_length,
961 GFP_ATOMIC );
962#else
963 cfg80211_rx_mgmt( pAdapter->dev,
964 pRemainChanCtx->action_pkt_buff.freq,
965 pRemainChanCtx->action_pkt_buff.frame_ptr,
966 pRemainChanCtx->action_pkt_buff.frame_length,
967 GFP_ATOMIC );
968#endif //LINUX_VERSION_CODE
969 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
970 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
971 pRemainChanCtx->action_pkt_buff.frame_length = 0;
972 pRemainChanCtx->action_pkt_buff.freq = 0;
973 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
974 }
Rashmi Ramannac7744532013-10-06 16:49:08 +0530975 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
976 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -0700977 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530978 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
979 {
Deepthi Gowri3124dcd2015-08-28 19:34:27 +0530980 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530981 /* since pRemainChanCtx->is_pending_roc_cancelled is
982 * set, it means Cancel Reamain on channel command is
983 * pending because remain on channel event was not
984 * ready when cancel ROC was issued.So issue
985 * cancel ROC now.
986 */
987 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
988 }
Deepthi Gowri3124dcd2015-08-28 19:34:27 +0530989 else
990 {
991 mutex_unlock(&pHddCtx->roc_lock);
992 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700993 }
994 else
995 {
Deepthi Gowri3124dcd2015-08-28 19:34:27 +0530996 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700997 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
998 }
999 return;
1000}
1001
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301002int __wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001003#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1004 struct wireless_dev *wdev,
1005#else
1006 struct net_device *dev,
1007#endif
1008 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -07001009{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001010#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1011 struct net_device *dev = wdev->netdev;
1012#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001013 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07001014 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +05301015 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301016 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1017 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301018 u64 cookie_dummy;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301019
1020 ENTER();
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301021 cookie_dummy = cookie << 32;
1022 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1023 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
1024 pAdapter->sessionId, cookie_dummy));
1025 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -07001026
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301027 status = wlan_hdd_validate_context(pHddCtx);
1028
1029 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001030 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301031 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001032 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301033 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
1034
Jeff Johnson295189b2012-06-20 16:38:30 -07001035 /* FIXME cancel currently running remain on chan.
1036 * Need to check cookie and cancel accordingly
1037 */
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +05301038 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +05301039 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001040 if( (cfgState->remain_on_chan_ctx == NULL) ||
1041 (cfgState->remain_on_chan_ctx->cookie != cookie) )
1042 {
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301043 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001044 hddLog( LOGE,
1045 "%s: No Remain on channel pending with specified cookie value",
1046 __func__);
1047 return -EINVAL;
1048 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301049 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
1050 {
Deepthi Gowri0e5c5d32015-03-30 13:52:53 +05301051 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301052 /* wait until remain on channel ready event received
1053 * for already issued remain on channel request */
1054 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
1055 msecs_to_jiffies(WAIT_REM_CHAN_READY));
1056 if (0 >= status)
1057 {
1058 hddLog( LOGE,
1059 "%s: timeout waiting for remain on channel ready indication %d",
1060 __func__, status);
Swaroop Golti05f63402015-07-22 11:59:59 +05301061 mutex_lock(&pHddCtx->roc_lock);
1062 if (cfgState->remain_on_chan_ctx)
1063 cfgState->remain_on_chan_ctx->is_pending_roc_cancelled = TRUE;
1064 mutex_unlock(&pHddCtx->roc_lock);
Abhishek Singh837adf22015-10-01 17:37:37 +05301065 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
1066 WLAN_LOG_INDICATOR_HOST_DRIVER,
1067 WLAN_LOG_REASON_HDD_TIME_OUT,
1068 FALSE, TRUE);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301069 return 0;
1070
1071 }
Deepthi Gowri0e5c5d32015-03-30 13:52:53 +05301072 mutex_lock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301073 }
1074 else
1075 {
1076 hddLog( LOG1, FL("Cancel ROC event is already pending, "
1077 "waiting for ready on channel indication.") );
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +05301078 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301079 return 0;
1080 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301081 if (NULL != cfgState->remain_on_chan_ctx)
1082 {
1083 vos_timer_stop(&cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer);
1084 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
1085 {
Deepthi Gowri0e5c5d32015-03-30 13:52:53 +05301086 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301087 hddLog( LOG1,
1088 FL("ROC timer cancellation in progress,"
1089 " wait for completion"));
1090 status = wait_for_completion_interruptible_timeout(
1091 &pAdapter->cancel_rem_on_chan_var,
1092 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1093 if (0 >= status)
1094 {
1095 hddLog( LOGE,
1096 "%s:wait on cancel_rem_on_chan_var failed %d",
1097 __func__, status);
1098 }
1099 return 0;
1100 }
1101 else
1102 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
1103 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001104 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Abhishek Singh4892e962015-12-30 11:18:58 +05301105 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001106 /* Issue abort remain on chan request to sme.
1107 * The remain on channel callback will make sure the remain_on_chan
1108 * expired event is sent.
1109 */
Abhishek Singh36b7c532015-03-13 15:50:54 +05301110 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
1111 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
Deepthi Gowri70498252015-01-20 15:56:45 +05301112 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001113 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301114 tANI_U8 sessionId = pAdapter->sessionId;
Deepthi Gowri70498252015-01-20 15:56:45 +05301115 if (eHAL_STATUS_SUCCESS !=
1116 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
1117 sessionId ))
1118 {
1119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1120 FL("Failed to Cancel Remain on Channel"));
1121 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001122 }
Deepthi Gowri70498252015-01-20 15:56:45 +05301123 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001124 {
1125 WLANSAP_CancelRemainOnChannel(
Deepthi Gowri70498252015-01-20 15:56:45 +05301126 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001127 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301128 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001129 {
1130 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
1131 __func__, pAdapter->device_mode);
1132 return -EIO;
1133 }
c_hpothu7f63e882013-10-02 19:13:35 +05301134 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -07001135 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +05301136 if (0 >= status)
1137 {
1138 hddLog( LOGE,
1139 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
1140 }
Sushant Kaushik83392fa2015-05-05 17:44:40 +05301141 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301142
1143 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07001144 return 0;
1145}
1146
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301147int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001148#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301149 struct wireless_dev *wdev,
1150#else
1151 struct net_device *dev,
1152#endif
1153 u64 cookie )
1154{
1155 int ret;
1156
1157 vos_ssr_protect(__func__);
1158 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
1159#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1160 wdev,
1161#else
1162 dev,
1163#endif
1164 cookie);
1165 vos_ssr_unprotect(__func__);
1166
1167 return ret;
1168}
1169
1170
1171#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1172int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001173 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -07001174#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001175 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -07001176 bool channel_type_valid,
1177#endif
1178 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001179 const u8 *buf, size_t len, bool no_cck,
1180 bool dont_wait_for_ack, u64 *cookie )
1181#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301182int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001183 struct ieee80211_channel *chan, bool offchan,
1184 enum nl80211_channel_type channel_type,
1185 bool channel_type_valid, unsigned int wait,
1186 const u8 *buf, size_t len, bool no_cck,
1187 bool dont_wait_for_ack, u64 *cookie )
1188#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301189int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001190 struct ieee80211_channel *chan, bool offchan,
1191 enum nl80211_channel_type channel_type,
1192 bool channel_type_valid, unsigned int wait,
1193 const u8 *buf, size_t len, u64 *cookie )
1194#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301195int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001196 struct ieee80211_channel *chan,
1197 enum nl80211_channel_type channel_type,
1198 bool channel_type_valid,
1199 const u8 *buf, size_t len, u64 *cookie )
1200#endif //LINUX_VERSION_CODE
1201{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001202#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1203 struct net_device *dev = wdev->netdev;
1204#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001205 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301206 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri7374e282015-08-26 19:22:58 +05301207 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301208 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnsone7245742012-09-05 17:12:55 -07001209 tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
1210 tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
Mukul Sharma1e5d0b72014-07-01 19:22:21 +05301211 tActionFrmType actionFrmType = WLAN_HDD_ACTION_FRM_TYPE_MAX;
Jeff Johnsone7245742012-09-05 17:12:55 -07001212 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301213 int status;
Jeff Johnsone7245742012-09-05 17:12:55 -07001214
Jeff Johnson295189b2012-06-20 16:38:30 -07001215#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1216 hdd_adapter_t *goAdapter;
1217#endif
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301218
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301219 ENTER();
1220 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301221 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
1222 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301223 status = wlan_hdd_validate_context(pHddCtx);
1224
1225 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001226 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301227 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001228 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301229
c_hpothu7f63e882013-10-02 19:13:35 +05301230 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
1231 __func__, pAdapter->device_mode, type);
1232
1233
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001234 if ((type == SIR_MAC_MGMT_FRAME) &&
1235 (subType == SIR_MAC_MGMT_ACTION) &&
1236 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
1237 {
1238 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301239#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001240 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001241 {
1242 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
1243 actionFrmType);
1244 }
1245 else
1246 {
1247 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
1248 p2p_action_frame_type[actionFrmType]);
1249 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1250 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1251 {
1252 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1253 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001254 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001255 }
1256 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1257 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1258 {
1259 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1260 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
1261 " completed state");
1262 }
1263 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001264#endif
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301265 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001266
Jeff Johnsone7245742012-09-05 17:12:55 -07001267#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1268 noack = dont_wait_for_ack;
1269#endif
1270
Deepthi Gowri7374e282015-08-26 19:22:58 +05301271
Jeff Johnsone7245742012-09-05 17:12:55 -07001272 //If the wait is coming as 0 with off channel set
1273 //then set the wait to 200 ms
1274 if (offchan && !wait)
Deepthi Gowri22d08752015-02-05 15:07:40 +05301275 {
Ganesh Kondabattini7f6049c2015-02-20 20:39:05 +05301276 wait = ACTION_FRAME_DEFAULT_WAIT;
Deepthi Gowri7374e282015-08-26 19:22:58 +05301277 mutex_lock(&pHddCtx->roc_lock);
1278 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Ganesh Kondabattini7f6049c2015-02-20 20:39:05 +05301279 if (pRemainChanCtx)
1280 {
1281 tANI_U32 current_time = vos_timer_get_system_time();
1282 int remaining_roc_time = ((int) pRemainChanCtx->duration -
1283 (current_time - pAdapter->startRocTs));
1284 if ( remaining_roc_time > ACTION_FRAME_DEFAULT_WAIT)
1285 wait = remaining_roc_time;
1286 }
Deepthi Gowri7374e282015-08-26 19:22:58 +05301287 mutex_unlock(&pHddCtx->roc_lock);
Deepthi Gowri22d08752015-02-05 15:07:40 +05301288 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001289
Jeff Johnson295189b2012-06-20 16:38:30 -07001290 //Call sme API to send out a action frame.
1291 // OR can we send it directly through data path??
1292 // After tx completion send tx status back.
1293 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1294 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1295 )
1296 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001297 if (type == SIR_MAC_MGMT_FRAME)
1298 {
1299 if (subType == SIR_MAC_MGMT_PROBE_RSP)
1300 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301301 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -07001302 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301303 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001304 goto err_rem_channel;
1305 }
1306 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
1307 (subType == SIR_MAC_MGMT_DEAUTH))
1308 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001309 /* During EAP failure or P2P Group Remove supplicant
1310 * is sending del_station command to driver. From
1311 * del_station function, Driver will send deauth frame to
1312 * p2p client. No need to send disassoc frame from here.
1313 * so Drop the frame here and send tx indication back to
1314 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -07001315 */
1316 tANI_U8 dstMac[ETH_ALEN] = {0};
1317 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07001318 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001319 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -08001320 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001321 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08001322 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001323 goto err_rem_channel;
1324 }
1325 }
1326 }
1327
1328 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001329 {
1330 if ( !noack )
1331 {
1332 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1333 __func__);
1334 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1335 }
1336 else
1337 {
1338 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1339 __func__);
1340 return -EBUSY;
1341 }
1342 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001343
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301344 if( subType == SIR_MAC_MGMT_ACTION)
1345 {
1346 hddLog( LOG1, "Action frame tx request : %s",
1347 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1348 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001349
1350#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1351 goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );
1352
1353 //If GO adapter exists and operating on same frequency
1354 //then we will not request remain on channel
1355 if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
1356 == goAdapter->sessionCtx.ap.operatingChannel ) )
1357 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301358 /* if GO exist and is not off channel
1359 * wait time should be zero.
1360 */
1361 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001362 goto send_frame;
1363 }
1364#endif
1365
1366#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1367 if( offchan && wait)
1368 {
1369 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301370 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001371 // In case of P2P Client mode if we are already
1372 // on the same channel then send the frame directly
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301373 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri7374e282015-08-26 19:22:58 +05301374 pRemainChanCtx = cfgState->remain_on_chan_ctx;
1375 if( (pRemainChanCtx != NULL) &&
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301376 (cfgState->current_freq == chan->center_freq)
1377 )
1378 {
1379 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
Deepthi Gowri7374e282015-08-26 19:22:58 +05301380 &pRemainChanCtx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301381 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301382 /* Some times FW is taking almost 500 msec for
1383 * full 15 retries, which leads to ROC expiration
1384 * by the time peer gets response from other peer.
1385 * Therefore as part of temporary fix , in host
1386 * ROC time is extended. For frames where we are
1387 * expecting response from peer , its extended by
1388 * 500 msec to make ROC wait time as 1 sec and
1389 * in other cases its extended by 300 msec to make
1390 * total ROC wait as 500 msec.
1391 * TODO: FW needs to fix as why 15 retry is taking
1392 * such long time.
1393 */
1394 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1395 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1396 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1397 wait = wait + ACTION_FRAME_RSP_WAIT;
1398 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1399 actionFrmType == WLAN_HDD_INVITATION_RESP )
1400 wait = wait + ACTION_FRAME_ACK_WAIT;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301401 vos_timer_stop(
Deepthi Gowri7374e282015-08-26 19:22:58 +05301402 &pRemainChanCtx->hdd_remain_on_chan_timer);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301403 status = vos_timer_start(
Deepthi Gowri7374e282015-08-26 19:22:58 +05301404 &pRemainChanCtx->hdd_remain_on_chan_timer,
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301405 wait);
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301406
1407 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301408
1409 hddLog(VOS_TRACE_LEVEL_INFO,
1410 "action frame: extending the wait time %u",
1411 wait);
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301412
1413 if ( status != VOS_STATUS_SUCCESS )
1414 {
1415 hddLog( LOGE, "Remain on Channel timer start failed");
1416 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301417 goto send_frame;
1418 }
1419 else
1420 {
1421 if ( TRUE ==
1422 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1423 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301424 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301425 hddLog(VOS_TRACE_LEVEL_INFO,
1426 "action frame tx: waiting for completion of ROC ");
1427
1428 status = wait_for_completion_interruptible_timeout(
1429 &pAdapter->cancel_rem_on_chan_var,
1430 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1431 if (0 >= status)
1432 {
1433 hddLog( LOGE,
1434 "%s:wait on cancel_rem_on_chan_var failed %d",
1435 __func__, status);
1436 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301437 goto bypass_lock;
vamsida0e5ab2013-12-26 14:33:27 +05301438 }
1439 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301440 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301441 mutex_unlock(&pHddCtx->roc_lock);
1442bypass_lock:
Rashmi Ramannac7744532013-10-06 16:49:08 +05301443 hddLog(VOS_TRACE_LEVEL_INFO,
1444 "action frame: Request ROC for wait time %u", wait);
Jeff Johnson295189b2012-06-20 16:38:30 -07001445 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001446 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001447 chan,
1448#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1449 channel_type,
1450#endif
1451 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301452 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001453
1454 if(0 != status)
1455 {
1456 if( (-EBUSY == status) &&
1457 (cfgState->current_freq == chan->center_freq) )
1458 {
1459 goto send_frame;
1460 }
1461 goto err_rem_channel;
1462 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001463 /* Wait for driver to be ready on the requested channel */
1464 status = wait_for_completion_interruptible_timeout(
1465 &pAdapter->offchannel_tx_event,
1466 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301467 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001468 {
c_hpothu7f63e882013-10-02 19:13:35 +05301469 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001470 goto err_rem_channel;
1471 }
1472 }
1473 else if ( offchan )
1474 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001475 /* Check before sending action frame
1476 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001477 if(NULL == cfgState->remain_on_chan_ctx)
1478 {
1479 goto err_rem_channel;
1480 }
1481 }
1482 send_frame:
1483#endif
1484
Jeff Johnsone7245742012-09-05 17:12:55 -07001485 if(!noack)
1486 {
1487 cfgState->buf = vos_mem_malloc( len ); //buf;
1488 if( cfgState->buf == NULL )
1489 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001490
Jeff Johnsone7245742012-09-05 17:12:55 -07001491 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001492
Jeff Johnsone7245742012-09-05 17:12:55 -07001493 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001494
Ganesh Kondabattinicdacf812015-09-01 12:36:09 +05301495 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001496#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001497 if( cfgState->remain_on_chan_ctx )
1498 {
1499 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1500 *cookie = cfgState->action_cookie;
1501 }
1502 else
1503 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001504#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001505 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001506 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001507#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001508 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001509#endif
Ganesh Kondabattinicdacf812015-09-01 12:36:09 +05301510 mutex_unlock(&pHddCtx->roc_lock);
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301511 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001512
1513 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001514 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1515 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001516 )
1517 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001518 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001519
Jeff Johnsone7245742012-09-05 17:12:55 -07001520 if ((type == SIR_MAC_MGMT_FRAME) &&
1521 (subType == SIR_MAC_MGMT_ACTION) &&
1522 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
Jeff Johnson295189b2012-06-20 16:38:30 -07001523 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001524 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301525 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001526 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001527 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001528 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301529 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001530 }
1531 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1532 {
1533 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301534 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001535 }
1536 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301537
Jeff Johnson295189b2012-06-20 16:38:30 -07001538 if (eHAL_STATUS_SUCCESS !=
1539 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301540 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001541 {
1542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1543 "%s: sme_sendAction returned fail", __func__);
1544 goto err;
1545 }
1546 }
Abhishek Singh36b7c532015-03-13 15:50:54 +05301547 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001548 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001549 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001550 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001551 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001552 {
1553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1554 "%s: WLANSAP_SendAction returned fail", __func__);
1555 goto err;
1556 }
1557 }
1558
1559 return 0;
1560err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001561 if(!noack)
1562 {
1563 hdd_sendActionCnf( pAdapter, FALSE );
1564 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001565 return 0;
1566err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001567 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001568 cfg80211_mgmt_tx_status(
1569#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1570 pAdapter->dev->ieee80211_ptr,
1571#else
1572 pAdapter->dev,
1573#endif
1574 *cookie, buf, len, FALSE, GFP_KERNEL );
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301575 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07001576 return 0;
1577}
1578
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05301579#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
1580int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
1581 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
1582#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301583int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
1584 struct ieee80211_channel *chan, bool offchan,
1585#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1586 enum nl80211_channel_type channel_type,
1587 bool channel_type_valid,
1588#endif
1589 unsigned int wait,
1590 const u8 *buf, size_t len, bool no_cck,
1591 bool dont_wait_for_ack, u64 *cookie )
1592#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1593int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1594 struct ieee80211_channel *chan, bool offchan,
1595 enum nl80211_channel_type channel_type,
1596 bool channel_type_valid, unsigned int wait,
1597 const u8 *buf, size_t len, bool no_cck,
1598 bool dont_wait_for_ack, u64 *cookie )
1599#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1600int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1601 struct ieee80211_channel *chan, bool offchan,
1602 enum nl80211_channel_type channel_type,
1603 bool channel_type_valid, unsigned int wait,
1604 const u8 *buf, size_t len, u64 *cookie )
1605#else
1606int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1607 struct ieee80211_channel *chan,
1608 enum nl80211_channel_type channel_type,
1609 bool channel_type_valid,
1610 const u8 *buf, size_t len, u64 *cookie )
1611#endif //LINUX_VERSION_CODE
1612{
1613 int ret;
1614
1615 vos_ssr_protect(__func__);
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05301616#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
1617 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan,
1618 params->wait, params->buf, params->len,
1619 params->no_cck, params->dont_wait_for_ack,
1620 cookie);
1621#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301622 ret = __wlan_hdd_mgmt_tx(wiphy, wdev,
1623 chan, offchan,
1624#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1625 channel_type,
1626 channel_type_valid,
1627#endif
1628 wait,
1629 buf, len, no_cck,
1630 dont_wait_for_ack, cookie);
1631#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1632 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1633 channel_type, channel_type_valid, wait,
1634 buf, len, no_cck,
1635 dont_wait_for_ack, cookie);
1636#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1637 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1638 channel_type, channel_type_valid, wait,
1639 buf, len, cookie);
1640#else
1641 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, channel_type,
1642 channel_type_valid, buf, len, cookie);
1643#endif //LINUX_VERSION_CODE
1644 vos_ssr_unprotect(__func__);
1645
1646 return ret;
1647}
1648
Jeff Johnson295189b2012-06-20 16:38:30 -07001649#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001650#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301651int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001652 struct wireless_dev *wdev,
1653 u64 cookie)
1654{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301655 u64 cookie_dummy;
1656 cookie_dummy = cookie << 32;
1657 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1658 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001659 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1660}
1661#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301662int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001663 struct net_device *dev,
1664 u64 cookie)
1665{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301666 u64 cookie_dummy;
1667 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1668 cookie_dummy = cookie << 32;
1669 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1670 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1671 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001672 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1673}
1674#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001675#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001676
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301677#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1678#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1679int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1680 struct wireless_dev *wdev,
1681 u64 cookie)
1682{
1683 int ret;
1684
1685 vos_ssr_protect(__func__);
1686 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1687 vos_ssr_unprotect(__func__);
1688
1689 return ret;
1690}
1691#else
1692int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1693 struct net_device *dev,
1694 u64 cookie)
1695{
1696 int ret;
1697
1698 vos_ssr_protect(__func__);
1699 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie);
1700 vos_ssr_unprotect(__func__);
1701
1702 return ret;
1703}
1704#endif
1705#endif
1706
Jeff Johnson295189b2012-06-20 16:38:30 -07001707void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1708{
1709 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1710
Jeff Johnsone7245742012-09-05 17:12:55 -07001711 cfgState->actionFrmState = HDD_IDLE;
1712
Jeff Johnson295189b2012-06-20 16:38:30 -07001713 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
1714 if( NULL == cfgState->buf )
1715 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001716 return;
1717 }
1718
1719 /* If skb is NULL it means this packet was received on CFG80211 interface
1720 * else it was received on Monitor interface */
1721 if( cfgState->skb == NULL )
1722 {
1723 /*
1724 * buf is the same pointer it passed us to send. Since we are sending
1725 * it through control path, we use different buffers.
1726 * In case of mac80211, they just push it to the skb and pass the same
1727 * data while sending tx ack status.
1728 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001729 cfg80211_mgmt_tx_status(
1730#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1731 pAdapter->dev->ieee80211_ptr,
1732#else
1733 pAdapter->dev,
1734#endif
1735 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001736 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1737 vos_mem_free( cfgState->buf );
1738 cfgState->buf = NULL;
1739 }
1740 else
1741 {
1742 hdd_adapter_t* pMonAdapter =
1743 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1744 if( pMonAdapter == NULL )
1745 {
1746 hddLog( LOGE, "Not able to get Monitor Adapter");
1747 cfgState->skb = NULL;
1748 vos_mem_free( cfgState->buf );
1749 cfgState->buf = NULL;
1750 complete(&pAdapter->tx_action_cnf_event);
1751 return;
1752 }
1753 /* Send TX completion feedback over monitor interface. */
1754 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1755 cfgState->skb = NULL;
1756 vos_mem_free( cfgState->buf );
1757 cfgState->buf = NULL;
1758 /* Look for the next Mgmt packet to TX */
1759 hdd_mon_tx_mgmt_pkt(pAdapter);
1760 }
1761 complete(&pAdapter->tx_action_cnf_event);
1762}
1763
1764/**
1765 * hdd_setP2pNoa
1766 *
1767 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301768 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001769 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1770 *
1771 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301772 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001773 *
1774 *ASSUMPTIONS:
1775 *
1776 *
1777 *NOTE:
1778 *
1779 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301780 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001781 *
1782 * @return Status
1783 */
1784
1785int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1786{
1787 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1788 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1789 VOS_STATUS status = VOS_STATUS_SUCCESS;
1790 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001791 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001792 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001793 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001794
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001795 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001796 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301797 {
1798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1799 "%s: strnchr failed to find delimeter",__func__);
1800 return -EINVAL;
1801 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001802 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001803 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1804 if (ret < 3)
1805 {
1806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1807 "%s: P2P_SET GO NoA: fail to read param "
Sushant Kaushik87787972015-09-11 16:05:00 +05301808 "count=%d duration=%d interval=%d ",
kalikinkar dhara19d77182013-11-12 14:29:46 -08001809 __func__, count, start_time, duration);
1810 return -EINVAL;
1811 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001813 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001814 __func__, count, start_time, duration);
1815 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001816 /* PS Selection
1817 * Periodic NoA (2)
1818 * Single NOA (4)
1819 */
1820 NoA.opp_ps = 0;
1821 NoA.ctWindow = 0;
1822 if (count == 1)
1823 {
1824 NoA.duration = 0;
1825 NoA.single_noa_duration = duration;
1826 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1827 }
1828 else
1829 {
1830 NoA.duration = duration;
1831 NoA.single_noa_duration = 0;
1832 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1833 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001834 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001835 NoA.count = count;
1836 NoA.sessionid = pAdapter->sessionId;
1837
1838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1839 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1840 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001841 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001842 NoA.ctWindow, NoA.duration, NoA.interval,
1843 NoA.count, NoA.single_noa_duration,
1844 NoA.psSelection);
1845
1846 sme_p2pSetPs(hHal, &NoA);
1847 return status;
1848}
1849
1850/**
1851 * hdd_setP2pOpps
1852 *
1853 *FUNCTION:
1854 * This function is called from hdd_hostapd_ioctl function when Driver
1855 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1856 *
1857 *LOGIC:
1858 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1859 *
1860 *ASSUMPTIONS:
1861 *
1862 *
1863 *NOTE:
1864 *
1865 * @param dev Pointer to net device structure
1866 * @param command Pointer to command
1867 *
1868 * @return Status
1869 */
1870
1871int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1872{
1873 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1874 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1875 VOS_STATUS status = VOS_STATUS_SUCCESS;
1876 tP2pPsConfig NoA;
1877 char *param;
1878 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001879 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001880
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001881 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001882 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301883 {
1884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1885 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001886 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05301887 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001888 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001889 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1890 if (ret < 3)
1891 {
1892 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1893 "%s: P2P_SET GO PS: fail to read param "
Sushant Kaushik87787972015-09-11 16:05:00 +05301894 " legacy_ps=%d opp_ps=%d ctwindow=%d ",
kalikinkar dhara19d77182013-11-12 14:29:46 -08001895 __func__, legacy_ps, opp_ps, ctwindow);
1896 return -EINVAL;
1897 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001898 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001899 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07001900 __func__, legacy_ps, opp_ps, ctwindow);
1901
1902 /* PS Selection
1903 * Opportunistic Power Save (1)
1904 */
1905
1906 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1907 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301908 * values are coming from wpa_supplicant as -1.
1909 * Example : User want to set ctWindow with 30 then wpa_cli command :
1910 * P2P_SET ctwindow 30
1911 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07001912 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301913 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001914 if (ctwindow != -1)
1915 {
1916
1917 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001918 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07001919 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
1920
1921 if (ctwindow != pAdapter->ctw)
1922 {
1923 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301924
Jeff Johnson295189b2012-06-20 16:38:30 -07001925 if(pAdapter->ops)
1926 {
1927 NoA.opp_ps = pAdapter->ops;
1928 NoA.ctWindow = pAdapter->ctw;
1929 NoA.duration = 0;
1930 NoA.single_noa_duration = 0;
1931 NoA.interval = 0;
1932 NoA.count = 0;
1933 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1934 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301935
Jeff Johnson295189b2012-06-20 16:38:30 -07001936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1937 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1938 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001939 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001940 NoA.ctWindow, NoA.duration, NoA.interval,
1941 NoA.count, NoA.single_noa_duration,
1942 NoA.psSelection);
1943
1944 sme_p2pSetPs(hHal, &NoA);
1945 }
1946 return 0;
1947 }
1948 }
1949
1950 if (opp_ps != -1)
1951 {
1952 pAdapter->ops = opp_ps;
1953
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301954 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07001955 {
1956 NoA.opp_ps = opp_ps;
1957 NoA.ctWindow = pAdapter->ctw;
1958 NoA.duration = 0;
1959 NoA.single_noa_duration = 0;
1960 NoA.interval = 0;
1961 NoA.count = 0;
1962 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1963 NoA.sessionid = pAdapter->sessionId;
1964
1965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1966 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1967 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001968 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001969 NoA.ctWindow, NoA.duration, NoA.interval,
1970 NoA.count, NoA.single_noa_duration,
1971 NoA.psSelection);
1972
1973 sme_p2pSetPs(hHal, &NoA);
1974 }
1975 }
1976 return status;
1977}
1978
1979int hdd_setP2pPs( struct net_device *dev, void *msgData )
1980{
1981 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1982 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1983 VOS_STATUS status = VOS_STATUS_SUCCESS;
1984 tP2pPsConfig NoA;
1985 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1986
1987 NoA.opp_ps = pappNoA->opp_ps;
1988 NoA.ctWindow = pappNoA->ctWindow;
1989 NoA.duration = pappNoA->duration;
1990 NoA.interval = pappNoA->interval;
1991 NoA.count = pappNoA->count;
1992 NoA.single_noa_duration = pappNoA->single_noa_duration;
1993 NoA.psSelection = pappNoA->psSelection;
1994 NoA.sessionid = pAdapter->sessionId;
1995
1996 sme_p2pSetPs(hHal, &NoA);
1997 return status;
1998}
Jeff Johnson295189b2012-06-20 16:38:30 -07001999
2000static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
2001{
2002 tANI_U8 sessionType;
2003
2004 switch( type )
2005 {
2006 case NL80211_IFTYPE_AP:
2007 sessionType = WLAN_HDD_SOFTAP;
2008 break;
2009 case NL80211_IFTYPE_P2P_GO:
2010 sessionType = WLAN_HDD_P2P_GO;
2011 break;
2012 case NL80211_IFTYPE_P2P_CLIENT:
2013 sessionType = WLAN_HDD_P2P_CLIENT;
2014 break;
2015 case NL80211_IFTYPE_STATION:
2016 sessionType = WLAN_HDD_INFRA_STATION;
2017 break;
2018 case NL80211_IFTYPE_MONITOR:
2019 sessionType = WLAN_HDD_MONITOR;
2020 break;
2021 default:
2022 sessionType = WLAN_HDD_INFRA_STATION;
2023 break;
2024 }
2025
2026 return sessionType;
2027}
2028
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002029#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302030struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002031 struct wiphy *wiphy, const char *name,
2032 enum nl80211_iftype type,
2033 u32 *flags, struct vif_params *params )
2034#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302035struct wireless_dev* __wlan_hdd_add_virtual_intf(
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002036 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
2037 u32 *flags, struct vif_params *params )
2038#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302039struct net_device* __wlan_hdd_add_virtual_intf(
Jeff Johnson295189b2012-06-20 16:38:30 -07002040 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
2041 u32 *flags, struct vif_params *params )
2042#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302043int __wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
Jeff Johnson295189b2012-06-20 16:38:30 -07002044 enum nl80211_iftype type,
2045 u32 *flags, struct vif_params *params )
2046#endif
2047{
2048 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302049 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05302050 hdd_scaninfo_t *pScanInfo = NULL;
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302051 int ret = 0;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302052
Jeff Johnson295189b2012-06-20 16:38:30 -07002053 ENTER();
2054
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302055 ret = wlan_hdd_validate_context(pHddCtx);
2056 if (0 != ret)
2057 {
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302058#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2059 return ERR_PTR(-EINVAL);
2060#else
2061 return -EAGAIN;
2062#endif
2063 }
2064
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302065 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2066 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05302067 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
2068 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
2069 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002070 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07002071 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002072 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05302073#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2074 return ERR_PTR(-EINVAL);
2075#else
2076 return -EAGAIN;
2077#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002078 }
2079
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05302080 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2081 pScanInfo = &pHddCtx->scan_info;
2082 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
2083 (pHddCtx->scan_info.mScanPending))
2084 {
2085 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
2086 eCSR_SCAN_ABORT_DEFAULT);
2087 hddLog(VOS_TRACE_LEVEL_INFO,
2088 "%s: Abort Scan while adding virtual interface",__func__);
2089 }
2090
2091 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05302092 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
2093 ((NL80211_IFTYPE_P2P_GO == type) ||
2094 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07002095 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002096 /* Generate the P2P Interface Address. this address must be
2097 * different from the P2P Device Address.
2098 */
2099 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
2100 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302101 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07002102 wlan_hdd_get_session_type(type),
2103 name, p2pDeviceAddress.bytes,
2104 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07002105 }
2106 else
2107 {
2108 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
2109 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
2110 }
2111
2112 if( NULL == pAdapter)
2113 {
2114 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
2115#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05302116 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002117#else
2118 return -EINVAL;
2119#endif
2120 }
Masti, Narayanraddi41d82f02015-06-12 14:04:11 +05302121
Masti, Narayanraddi575ccc72015-08-17 18:04:57 +05302122 if ((type == NL80211_IFTYPE_P2P_CLIENT) ||
2123 (type == NL80211_IFTYPE_P2P_GO))
2124 {
2125 /* Below function Notifies Mode change and
2126 * If p2p session is detected then invokes functionality to
2127 * Teardown TDLS links and disable offchannel if any. Since
2128 * TDLS is not supported in case of concurrency.
2129 */
2130 hddLog(LOG1, FL("Interface type = %d"), type);
2131 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
2132 }
Masti, Narayanraddi41d82f02015-06-12 14:04:11 +05302133
Jeff Johnson295189b2012-06-20 16:38:30 -07002134 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002135#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2136 return pAdapter->dev->ieee80211_ptr;
2137#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07002138 return pAdapter->dev;
2139#else
2140 return 0;
2141#endif
2142}
2143
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302144#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
2145struct wireless_dev* wlan_hdd_add_virtual_intf(
2146 struct wiphy *wiphy, const char *name,
2147 enum nl80211_iftype type,
2148 u32 *flags, struct vif_params *params )
2149#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2150struct wireless_dev* wlan_hdd_add_virtual_intf(
2151 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
2152 u32 *flags, struct vif_params *params )
2153#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2154struct net_device* wlan_hdd_add_virtual_intf(
2155 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
2156 u32 *flags, struct vif_params *params )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002157#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302158int wlan_hdd_add_virtual_intf( struct wiphy *wiphy, char *name,
2159 enum nl80211_iftype type,
2160 u32 *flags, struct vif_params *params )
2161#endif
2162{
2163#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)))
2164 struct wireless_dev* wdev;
2165#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2166 struct net_device* ndev;
2167#else
2168 int ret;
2169#endif
2170 vos_ssr_protect(__func__);
2171#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2172 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
2173 vos_ssr_unprotect(__func__);
2174 return wdev;
2175#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2176 ndev = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
2177 vos_ssr_unprotect(__func__);
2178 return ndev;
2179#else
2180 ret = __wlan_hdd_add_virtual_intf(wiphy, name, type, flags, params);
2181 vos_ssr_unprotect(__func__);
2182 return ret;
2183#endif
2184}
2185
2186#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2187int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
2188#else
2189int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002190#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002191{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002192#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2193 struct net_device *dev = wdev->netdev;
2194#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302195 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302196 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302197 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2198 int status;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302199
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302200 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07002201
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302202 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2203 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
2204 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302205 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
2206 __func__,pVirtAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002207
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302208 status = wlan_hdd_validate_context(pHddCtx);
2209
2210 if (0 != status)
2211 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302212 return status;
2213 }
2214
2215 wlan_hdd_release_intf_addr( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07002216 pVirtAdapter->macAddressCurrent.bytes );
2217
Agarwal Ashish3a38bd12014-06-12 15:16:52 +05302218 hdd_stop_adapter( pHddCtx, pVirtAdapter, VOS_TRUE);
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302219 hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE );
2220 EXIT();
2221 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002222}
2223
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302224#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2225int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
2226#else
2227int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
2228#endif
2229{
2230 int ret;
2231
2232 vos_ssr_protect(__func__);
2233#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2234 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
2235#else
2236 ret = __wlan_hdd_del_virtual_intf(wiphy, dev);
2237#endif
2238 vos_ssr_unprotect(__func__);
2239
2240 return ret;
2241}
2242
Jeff Johnson295189b2012-06-20 16:38:30 -07002243void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002244 tANI_U32 nFrameLength,
2245 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302246 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07002247{
2248 //Indicate a Frame over Monitor Intf.
2249 int rxstat;
2250 struct sk_buff *skb = NULL;
2251 int needed_headroom = 0;
2252 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
2253 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002254#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002255#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2256 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
2257#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002258#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002259 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
2260
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002261 if (NULL == pbFrames)
2262 {
2263 hddLog(LOGE, FL("NULL frame pointer"));
2264 return;
2265 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002266
2267 /* room for the radiotap header based on driver features
2268 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
2269 * RX flags.
2270 * */
2271 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
2272
2273 //alloc skb here
2274 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
2275 if (unlikely(NULL == skb))
2276 {
2277 hddLog( LOGW, FL("Unable to allocate skb"));
2278 return;
2279 }
2280 skb_reserve(skb, VPKT_SIZE_BUFFER);
2281 if (unlikely(skb_headroom(skb) < nFrameLength))
2282 {
2283 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2284 "HDD [%d]: Insufficient headroom, "
2285 "head[%p], data[%p], req[%d]",
2286 __LINE__, skb->head, skb->data, nFrameLength);
2287 kfree_skb(skb);
2288 return ;
2289 }
2290 // actually push the data
2291 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
2292 /* prepend radiotap information */
2293 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
2294 {
2295 hddLog( LOGE, FL("Not Able Add Radio Tap"));
2296 //free skb
2297 kfree_skb(skb);
2298 return ;
2299 }
2300
2301 skb_reset_mac_header( skb );
2302 skb->dev = pMonAdapter->dev;
2303 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002304 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002305#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002306#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302307 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
2308 HDD_WAKE_LOCK_DURATION,
2309 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Jeff Johnsone7245742012-09-05 17:12:55 -07002310#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002311#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002312 rxstat = netif_rx_ni(skb);
2313 if( NET_RX_SUCCESS == rxstat )
2314 {
2315 hddLog( LOG1, FL("Success"));
2316 }
2317 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302318 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07002319
2320 return ;
2321}
2322
Abhishek Singh7d624e12015-11-30 14:29:27 +05302323void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302324 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07002325 tANI_U8* pbFrames,
2326 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05302327 tANI_U32 rxChan,
Abhishek Singh7d624e12015-11-30 14:29:27 +05302328 tANI_S8 rxRssi)
Jeff Johnson295189b2012-06-20 16:38:30 -07002329{
2330 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302331 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07002332 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002333 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07002334 tActionFrmType actionFrmType;
2335 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302336 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05302337 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302338 VOS_STATUS status;
2339 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002340
Agarwal Ashishae800dd2015-06-24 12:44:48 +05302341 hddLog(VOS_TRACE_LEVEL_INFO, FL("Frame Type = %d Frame Length = %d"),
2342 frameType, nFrameLength);
Jeff Johnson295189b2012-06-20 16:38:30 -07002343
2344 if (NULL == pAdapter)
2345 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002346 hddLog(LOGE, FL("pAdapter is NULL"));
2347 return;
2348 }
2349
2350 if (0 == nFrameLength)
2351 {
2352 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2353 return;
2354 }
2355
2356 if (NULL == pbFrames)
2357 {
2358 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002359 return;
2360 }
2361
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002362 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2363 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2364
2365 /* Get pAdapter from Destination mac address of the frame */
2366 if ((type == SIR_MAC_MGMT_FRAME) &&
2367 (subType != SIR_MAC_MGMT_PROBE_REQ))
2368 {
2369 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
2370 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
2371 if (NULL == pAdapter)
2372 {
2373 /* Under assumtion that we don't receive any action frame
2374 * with BCST as destination we dropping action frame
2375 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08002376 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
2377 MAC_ADDRESS_STR ,
2378 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
2379 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08002380 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002381 return;
2382 }
2383 }
2384
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002385
Jeff Johnson295189b2012-06-20 16:38:30 -07002386 if (NULL == pAdapter->dev)
2387 {
2388 hddLog( LOGE, FL("pAdapter->dev is NULL"));
2389 return;
2390 }
2391
2392 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2393 {
2394 hddLog( LOGE, FL("pAdapter has invalid magic"));
2395 return;
2396 }
2397
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302398 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2399 if (NULL == pHddCtx)
2400 {
2401 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
2402 return;
2403 }
2404
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002405 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2406 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07002407 {
2408 hdd_adapter_t *pMonAdapter =
2409 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
2410
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002411 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07002412 {
2413 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
2414 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
2415 pbFrames, frameType);
2416 return;
2417 }
2418 }
2419
2420 //Channel indicated may be wrong. TODO
2421 //Indicate an action frame.
2422 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
2423 {
2424 freq = ieee80211_channel_to_frequency( rxChan,
2425 IEEE80211_BAND_2GHZ);
2426 }
2427 else
2428 {
2429 freq = ieee80211_channel_to_frequency( rxChan,
2430 IEEE80211_BAND_5GHZ);
2431 }
2432
Jeff Johnsone7245742012-09-05 17:12:55 -07002433 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302434
2435 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002436 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07002437 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002438 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
2439 {
2440 // public action frame
2441 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08002442 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 -08002443 // P2P action frames
2444 {
2445 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002446 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002447#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002448 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
2449 {
2450 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
2451 actionFrmType);
2452 }
2453 else
2454 {
2455 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
2456 p2p_action_frame_type[actionFrmType]);
2457 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
2458 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2459 {
2460 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
2461 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002462 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002463 }
2464 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
2465 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
2466 {
2467 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08002468 hddLog(LOGE,"[P2P State]GO negotiation progress to "
2469 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002470 }
2471 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
2472 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2473 {
2474 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
2475 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
2476 " completed state Autonomous GO formation");
2477 }
2478 }
2479#endif
Deepthi Gowri0637d592015-09-16 12:34:02 +05302480 mutex_lock(&pHddCtx->roc_lock);
2481 pRemainChanCtx = cfgState->remain_on_chan_ctx;
2482
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302483 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
2484 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
2485 {
2486 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
2487 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
2488 actionFrmType == WLAN_HDD_INVITATION_REQ ||
2489 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
2490 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
2491 {
2492 hddLog( LOG1, "Extend RoC timer on reception of"
2493 " Action Frame");
2494 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
2495 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
2496 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
2497 else
2498 extend_time = ACTION_FRAME_DEFAULT_WAIT;
2499 if (completion_done(&pAdapter->rem_on_chan_ready_event))
2500 {
2501 vos_timer_stop(
2502 &pRemainChanCtx->hdd_remain_on_chan_timer);
2503 status = vos_timer_start(
2504 &pRemainChanCtx->hdd_remain_on_chan_timer,
2505 extend_time);
2506 if (status != VOS_STATUS_SUCCESS)
2507 {
2508 hddLog( LOGE, "ROC timer start failed");
2509 }
2510 }
2511 else
2512 {
2513 // Buffer Packet
2514 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2515 {
2516 pRemainChanCtx->action_pkt_buff.frame_length =
2517 nFrameLength;
2518 pRemainChanCtx->action_pkt_buff.freq = freq;
2519 pRemainChanCtx->action_pkt_buff.frame_ptr
2520 = vos_mem_malloc(nFrameLength);
2521 vos_mem_copy(
2522 pRemainChanCtx->action_pkt_buff.frame_ptr,
2523 pbFrames, nFrameLength);
2524 hddLog( LOGE,"%s:"
2525 "Action Pkt Cached successfully !!!", __func__);
2526 }
2527 else
2528 {
2529 hddLog( LOGE,"%s:"
2530 "Frames are pending. dropping frame !!!",
2531 __func__);
2532 }
Deepthi Gowri0637d592015-09-16 12:34:02 +05302533 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302534 return;
2535 }
2536 }
2537 }
2538 if (pRemainChanCtx != NULL &&
Deepthi Gowri12e2dae2015-12-07 17:32:09 +05302539 vos_timer_is_initialized(
2540 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) &&
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302541 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2542 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2543 hddLog( LOG1, "%s:"
2544 "Rcvd action frame after timer expired ", __func__);
2545
Deepthi Gowri0637d592015-09-16 12:34:02 +05302546 mutex_unlock(&pHddCtx->roc_lock);
2547
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302548 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2549 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2550 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2551 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2552 {
Deepthi Gowri0637d592015-09-16 12:34:02 +05302553 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302554 __func__);
Deepthi Gowri0637d592015-09-16 12:34:02 +05302555 hdd_sendActionCnf(pAdapter, TRUE);
2556 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002557 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002558#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002559 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 -07002560 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002561 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302562 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002563 MAC_ADDR_ARRAY(mac),rxRssi);
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302564
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002565 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2566 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002567 }
2568#endif
2569 }
Kaushik, Sushant507a8612014-10-21 17:00:55 +05302570
2571 pScanInfo = &pHddCtx->scan_info;
2572 if ((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2573 {
2574 hddLog(LOGE,"Action frame received when Scanning is in"
2575 " progress. Abort Scan.");
2576 hdd_abort_mac_scan(pAdapter->pHddCtx,
2577 pScanInfo->sessionId,
2578 eCSR_SCAN_ABORT_DEFAULT);
2579 }
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302580
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002581 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2582 {
2583 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2584 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2585 {
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302586 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] Action type[%d] <--- OTA",
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002587 actionFrmType);
2588 }
2589 else
2590 {
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302591 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] %s <--- OTA",
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002592 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002593 }
2594 }
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302595
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002596 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
2597 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
2598 {
Kumar Anand82c009f2014-05-29 00:29:42 -07002599 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
2600 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07002601 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002602 }
2603
Jeff Johnson295189b2012-06-20 16:38:30 -07002604 //Indicate Frame Over Normal Interface
2605 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
Anand N Sunkad7bfc8e42015-07-29 09:59:45 +05302606#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
2607 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames,
2608 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED);
2609#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05302610 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames,
2611 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
2612#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002613 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, 0,
2614 pbFrames, nFrameLength,
2615 GFP_ATOMIC );
2616#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
Jeff Johnson295189b2012-06-20 16:38:30 -07002617 cfg80211_rx_mgmt( pAdapter->dev, freq, 0,
2618 pbFrames, nFrameLength,
2619 GFP_ATOMIC );
2620#else
2621 cfg80211_rx_mgmt( pAdapter->dev, freq,
2622 pbFrames, nFrameLength,
2623 GFP_ATOMIC );
2624#endif //LINUX_VERSION_CODE
2625}
2626
2627/*
2628 * ieee80211_add_rx_radiotap_header - add radiotap header
2629 */
2630static int hdd_wlan_add_rx_radiotap_hdr (
2631 struct sk_buff *skb, int rtap_len, int flag )
2632{
2633 u8 rtap_temp[20] = {0};
2634 struct ieee80211_radiotap_header *rthdr;
2635 unsigned char *pos;
2636 u16 rx_flags = 0;
2637
2638 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
2639
2640 /* radiotap header, set always present flags */
2641 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
2642 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
2643 rthdr->it_len = cpu_to_le16(rtap_len);
2644
2645 pos = (unsigned char *) (rthdr + 1);
2646
2647 /* the order of the following fields is important */
2648
2649 /* IEEE80211_RADIOTAP_FLAGS */
2650 *pos = 0;
2651 pos++;
2652
2653 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
2654 /* ensure 2 byte alignment for the 2 byte field as required */
2655 if ((pos - (u8 *)rthdr) & 1)
2656 pos++;
2657 put_unaligned_le16(rx_flags, pos);
2658 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302659
Jeff Johnson295189b2012-06-20 16:38:30 -07002660 // actually push the data
2661 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
2662
2663 return 0;
2664}
2665
2666static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
2667 hdd_cfg80211_state_t* cfgState,
2668 tANI_BOOLEAN actionSendSuccess )
2669{
2670 struct ieee80211_radiotap_header *rthdr;
2671 unsigned char *pos;
2672 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002673#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002674#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2675 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
2676#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002677#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002678
2679 /* 2 Byte for TX flags and 1 Byte for Retry count */
2680 u32 rtHdrLen = sizeof(*rthdr) + 3;
2681
2682 u8 *data;
2683
2684 /* We have to return skb with Data starting with MAC header. We have
2685 * copied SKB data starting with MAC header to cfgState->buf. We will pull
2686 * entire skb->len from skb and then we will push cfgState->buf to skb
2687 * */
2688 if( NULL == skb_pull(skb, skb->len) )
2689 {
2690 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
2691 kfree_skb(cfgState->skb);
2692 return;
2693 }
2694
2695 data = skb_push( skb, cfgState->len );
2696
2697 if (data == NULL)
2698 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08002699 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07002700 kfree_skb( cfgState->skb );
2701 return;
2702 }
2703
2704 memcpy( data, cfgState->buf, cfgState->len );
2705
2706 /* send frame to monitor interfaces now */
2707 if( skb_headroom(skb) < rtHdrLen )
2708 {
2709 hddLog( LOGE, FL("No headroom for rtap header"));
2710 kfree_skb(cfgState->skb);
2711 return;
2712 }
2713
2714 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
2715
2716 memset( rthdr, 0, rtHdrLen );
2717 rthdr->it_len = cpu_to_le16( rtHdrLen );
2718 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
2719 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
2720 );
2721
2722 pos = (unsigned char *)( rthdr+1 );
2723
2724 // Fill TX flags
2725 *pos = actionSendSuccess;
2726 pos += 2;
2727
2728 // Fill retry count
2729 *pos = 0;
2730 pos++;
2731
2732 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002733 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002734 skb->pkt_type = PACKET_OTHERHOST;
2735 skb->protocol = htons(ETH_P_802_2);
2736 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002737#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002738#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302739 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
2740 HDD_WAKE_LOCK_DURATION,
2741 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Jeff Johnsone7245742012-09-05 17:12:55 -07002742#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002743#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002744 if (in_interrupt())
2745 netif_rx( skb );
2746 else
2747 netif_rx_ni( skb );
2748
2749 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05302750 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302751 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07002752
2753}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05302754
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +05302755void __hdd_p2p_roc_work_queue(struct work_struct *work)
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05302756{
2757 hdd_adapter_t *pAdapter = container_of(to_delayed_work(work), hdd_adapter_t, roc_work);
2758 hddLog( VOS_TRACE_LEVEL_INFO, FL("%s: "), __func__);
2759 wlan_hdd_p2p_start_remain_on_channel(pAdapter);
2760 return;
2761}
2762
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +05302763void hdd_p2p_roc_work_queue(struct work_struct *work)
2764{
2765 vos_ssr_protect(__func__);
2766 __hdd_p2p_roc_work_queue(work);
2767 vos_ssr_unprotect(__func__);
2768 return;
2769}