blob: e3ab8b4b76a21a43a430635476346bd87db9ee3e [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302 * Copyright (c) 2012-2018 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);
Abhishek Singh09d4e4a2016-01-12 11:20:22 +053078 CASE_RETURN_STRING(SIR_MAC_ACTION_MHF);
Daram Sudha1f7e0e92013-12-17 07:52:31 +053079 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
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +0530135static v_BOOL_t wlan_hdd_is_type_p2p_action( const u8 *buf, uint32_t len )
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530136{
vamsi9bd92b72013-12-26 14:11:29 +0530137 const u8 *ouiPtr;
138
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +0530139 if (len < WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET + 1) {
140 return VOS_FALSE;
141 }
142
vamsi9bd92b72013-12-26 14:11:29 +0530143 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
144 WLAN_HDD_PUBLIC_ACTION_FRAME ) {
145 return VOS_FALSE;
146 }
147
148 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] !=
149 WLAN_HDD_VENDOR_SPECIFIC_ACTION ) {
150 return VOS_FALSE;
151 }
152
153 ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET];
154
155 if ( WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI ) {
156 return VOS_FALSE;
157 }
158
159 if ( buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] !=
160 WLAN_HDD_WFA_P2P_OUI_TYPE ) {
161 return VOS_FALSE;
162 }
163
Edhar, Mahesh Kumar11cf1972017-03-20 17:07:33 +0530164 return VOS_TRUE;
165}
166
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +0530167static bool hdd_p2p_is_action_type_rsp( const u8 *buf, uint32_t len )
Edhar, Mahesh Kumar11cf1972017-03-20 17:07:33 +0530168{
169 tActionFrmType actionFrmType;
170
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +0530171 if ( wlan_hdd_is_type_p2p_action(buf, len) )
Edhar, Mahesh Kumar11cf1972017-03-20 17:07:33 +0530172 {
173 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
174 if ( actionFrmType != WLAN_HDD_INVITATION_REQ &&
175 actionFrmType != WLAN_HDD_GO_NEG_REQ &&
176 actionFrmType != WLAN_HDD_DEV_DIS_REQ &&
177 actionFrmType != WLAN_HDD_PROV_DIS_REQ )
178 return VOS_TRUE;
179 }
180 return VOS_FALSE;
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +0530181}
Jeff Johnson295189b2012-06-20 16:38:30 -0700182
Jeff Johnson295189b2012-06-20 16:38:30 -0700183eHalStatus wlan_hdd_remain_on_channel_callback( tHalHandle hHal, void* pCtx,
184 eHalStatus status )
185{
186 hdd_adapter_t *pAdapter = (hdd_adapter_t*) pCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700187 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530188 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530189 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530190 rem_on_channel_request_type_t req_type;
191
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530192 if (pHddCtx == NULL)
193 {
194 hddLog(LOGE, "%s: Hdd Context is NULL", __func__);
195 return eHAL_STATUS_FAILURE;
196 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530197
198 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530199
200 pRemainChanCtx = cfgState->remain_on_chan_ctx;
201 if (pRemainChanCtx == NULL)
202 {
203 hddLog( LOGW,
204 "%s: No Rem on channel pending for which Rsp is received", __func__);
205 mutex_unlock(&pHddCtx->roc_lock);
206 return eHAL_STATUS_SUCCESS;
207 }
208
Rashmi Ramannac7744532013-10-06 16:49:08 +0530209 hddLog( VOS_TRACE_LEVEL_INFO,
210 "Received ROC rsp (request type %d, channel %d, cookie %llu",
211 pRemainChanCtx->rem_on_chan_request,
212 pRemainChanCtx->chan.center_freq,
213 pRemainChanCtx->cookie);
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +0530214 if(!VOS_IS_STATUS_SUCCESS(vos_timer_stop(
215 &pRemainChanCtx->hdd_remain_on_chan_timer)))
216 {
217 hddLog( LOGE, FL("Failed to stop hdd_remain_on_chan_timer"));
218 }
219 if(!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
220 &pRemainChanCtx->hdd_remain_on_chan_timer)))
221 {
222 hddLog( LOGE, FL("Failed to destroy hdd_remain_on_chan_timer"));
223 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530224 if ( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request )
Jeff Johnson295189b2012-06-20 16:38:30 -0700225 {
226 if( cfgState->buf )
227 {
Agrawal Ashishb10d0392015-08-06 16:18:20 +0530228 hddLog( LOG1,
Jeff Johnson295189b2012-06-20 16:38:30 -0700229 "%s: We need to receive yet an ack from one of tx packet",
230 __func__);
231 }
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800232 cfg80211_remain_on_channel_expired(
233#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
234 pRemainChanCtx->dev->ieee80211_ptr,
235#else
236 pRemainChanCtx->dev,
237#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 pRemainChanCtx->cookie,
239 &pRemainChanCtx->chan,
Yue Maf49ba872013-08-19 12:04:25 -0700240#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
241 pRemainChanCtx->chan_type,
242#endif
243 GFP_KERNEL);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530244 pAdapter->lastRocTs = vos_timer_get_system_time();
Jeff Johnson295189b2012-06-20 16:38:30 -0700245 }
246
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530247 req_type = pRemainChanCtx->rem_on_chan_request;
248 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700249
250 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Jeff Johnsone7245742012-09-05 17:12:55 -0700251 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
252 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -0700253 )
254 {
255 tANI_U8 sessionId = pAdapter->sessionId;
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530256 if( REMAIN_ON_CHANNEL_REQUEST == req_type )
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800257 {
258 sme_DeregisterMgmtFrame(
259 hHal, sessionId,
260 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
261 NULL, 0 );
262 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 }
Abhishek Singh36b7c532015-03-13 15:50:54 +0530264 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -0700265 {
266 WLANSAP_DeRegisterMgmtFrame(
267 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
268 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
269 NULL, 0 );
270 }
Deepthi Gowri200d15a2015-08-10 16:02:49 +0530271 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowriddda7a42016-08-16 17:05:13 +0530272 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530273 if ( pRemainChanCtx )
274 {
Deepthi Gowri75664652016-09-08 17:44:35 +0530275 /* Trigger kernel panic if ROC timer state is not set to unused state
276 * before freeing the ROC ctx.
277 */
278 if (VOS_TIMER_STATE_UNUSED != vos_timer_getCurrentState(
279 &pRemainChanCtx->hdd_remain_on_chan_timer))
280 VOS_BUG(0);
281
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530282 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
283 && pRemainChanCtx->action_pkt_buff.frame_length != 0)
284 {
285 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
286 }
Deepthi Gowriddda7a42016-08-16 17:05:13 +0530287 hddLog( LOG1, FL(
Jeff Johnsonc135a9a2017-09-19 08:37:24 -0700288 "Freeing ROC ctx cfgState->remain_on_chan_ctx=%pK"),
Deepthi Gowriddda7a42016-08-16 17:05:13 +0530289 cfgState->remain_on_chan_ctx);
290 vos_mem_free( pRemainChanCtx );
291 pRemainChanCtx = NULL;
292 cfgState->remain_on_chan_ctx = NULL;
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530293 }
Deepthi Gowri200d15a2015-08-10 16:02:49 +0530294 mutex_unlock(&pHddCtx->roc_lock);
Deepthi Gowri3e672f02015-01-30 17:04:08 +0530295 if (eHAL_STATUS_SUCCESS != status)
296 complete(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -0700297 complete(&pAdapter->cancel_rem_on_chan_var);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530298 pAdapter->is_roc_inprogress = FALSE;
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530299 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Jeff Johnson295189b2012-06-20 16:38:30 -0700300 return eHAL_STATUS_SUCCESS;
301}
302
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530303VOS_STATUS wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700304{
Jeff Johnson295189b2012-06-20 16:38:30 -0700305 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri7374e282015-08-26 19:22:58 +0530306 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530307 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700308 int status = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -0700309
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530310 if (NULL == pHddCtx)
311 {
312 hddLog(LOGE, "%s: HddCtx is NULL", __func__);
313 return VOS_STATUS_E_FAILURE;
314 }
315
316 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri7374e282015-08-26 19:22:58 +0530317 pRemainChanCtx = cfgState->remain_on_chan_ctx;
318 if(pRemainChanCtx != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -0700319 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530320 if(VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
Deepthi Gowri7374e282015-08-26 19:22:58 +0530321 &pRemainChanCtx->hdd_remain_on_chan_timer))
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530322 {
323 hddLog(VOS_TRACE_LEVEL_INFO,
324 "Cancel Existing ROC (cookie=%llu)",
Deepthi Gowri7374e282015-08-26 19:22:58 +0530325 pRemainChanCtx->cookie);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700326
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +0530327 if(!VOS_IS_STATUS_SUCCESS(vos_timer_stop(
328 &pRemainChanCtx->hdd_remain_on_chan_timer)))
329 {
330 hddLog( LOGE, FL("Failed to stop hdd_remain_on_chan_timer"));
331 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530332 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +0530333 /* Wait till remain on channel ready indication before issuing cancel
334 * remain on channel request, otherwise if remain on channel not
335 * received and if the driver issues cancel remain on channel then lim
Jeff Johnson295189b2012-06-20 16:38:30 -0700336 * will be in unknown state.
337 */
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530338 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress != TRUE)
Jeff Johnson295189b2012-06-20 16:38:30 -0700339 {
Deepthi Gowrief88a5f2015-04-06 14:41:46 +0530340 mutex_unlock(&pHddCtx->roc_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530341 status = wait_for_completion_interruptible_timeout(
342 &pAdapter->rem_on_chan_ready_event,
343 msecs_to_jiffies(WAIT_REM_CHAN_READY));
344 if (0 >= status)
345 {
Deepthi Gowri7374e282015-08-26 19:22:58 +0530346 mutex_lock(&pHddCtx->roc_lock);
347 pRemainChanCtx = cfgState->remain_on_chan_ctx;
348 if (pRemainChanCtx)
349 pRemainChanCtx->is_pending_roc_cancelled = TRUE;
350 mutex_unlock(&pHddCtx->roc_lock);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530351 hddLog( LOGE,
Deepthi Gowri7374e282015-08-26 19:22:58 +0530352 "%s: timeout waiting for remain on channel"
353 " ready indication %d",
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530354 __func__, status);
Abhishek Singh837adf22015-10-01 17:37:37 +0530355 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
356 WLAN_LOG_INDICATOR_HOST_DRIVER,
357 WLAN_LOG_REASON_HDD_TIME_OUT,
358 FALSE, TRUE);
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530359 return VOS_STATUS_E_FAILURE;
360 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700361
Deepthi Gowrief88a5f2015-04-06 14:41:46 +0530362 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri7374e282015-08-26 19:22:58 +0530363 pRemainChanCtx = cfgState->remain_on_chan_ctx;
364 if (NULL == pRemainChanCtx)
365 {
366 mutex_unlock(&pHddCtx->roc_lock);
367 hddLog( LOGE,
368 "%s-%d: pRemainChanCtx is NULL",
369 __func__, __LINE__);
370 return VOS_STATUS_E_FAILURE;
371 }
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530372 /* Check again if cancel remain on channel is started.
373 * If its started wait for its completiona and return.
374 */
375 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
376 {
377 mutex_unlock(&pHddCtx->roc_lock);
378 hddLog( LOG1,
379 "ROC timer cancellation in progress,"
380 " wait for completion");
381 status = wait_for_completion_interruptible_timeout(
382 &pAdapter->cancel_rem_on_chan_var,
383 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
384 if (0 >= status)
385 {
386 hddLog( LOGE,
387 "%s:wait on cancel_rem_on_chan_var failed %d",
388 __func__, status);
389 return VOS_STATUS_E_FAILURE;
390 }
391 return VOS_STATUS_SUCCESS;
392 }
393 else
394 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530395 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Abhishek Singh4892e962015-12-30 11:18:58 +0530396 mutex_unlock(&pHddCtx->roc_lock);
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530397
398 /* Issue abort remain on chan request to sme.
399 * The remain on channel callback will make sure the remain_on_chan
400 * expired event is sent.
401 */
402 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
Abhishek Singh36b7c532015-03-13 15:50:54 +0530403 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
404 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ))
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530405 {
406 if (eHAL_STATUS_SUCCESS !=
407 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
Deepthi Gowri70498252015-01-20 15:56:45 +0530408 pAdapter->sessionId ))
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530409 {
410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
411 FL("Failed to Cancel Remain on Channel"));
412 }
413 }
414 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
415 {
416 WLANSAP_CancelRemainOnChannel(
417 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
418 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700419
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530420 status = wait_for_completion_interruptible_timeout(
421 &pAdapter->cancel_rem_on_chan_var,
422 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
Abhishek Singh9afcc842016-03-24 10:34:12 +0530423 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530424 if (0 >= status)
425 {
Abhishek Singh9afcc842016-03-24 10:34:12 +0530426 hddLog(LOGE,
427 FL("Timeout waiting for cancel remain on channel ready indication %d"),
428 status);
429 return VOS_STATUS_E_FAILURE;
Abhishek Singhf81dfd02015-08-10 14:15:08 +0530430 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530431 }
432 else
433 {
434 hddLog( LOG1,
435 "ROC timer cancellation in progress,"
436 " wait for completion");
437 mutex_unlock(&pHddCtx->roc_lock);
438 status = wait_for_completion_interruptible_timeout(
439 &pAdapter->cancel_rem_on_chan_var,
440 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
441 if (0 >= status)
442 {
443 hddLog( LOGE,
444 "%s:wait on cancel_rem_on_chan_var failed %d",
445 __func__, status);
446 return VOS_STATUS_E_FAILURE;
447 }
448 return VOS_STATUS_SUCCESS;
449 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700450 }
Mahesh A Saptasagar60627942014-10-13 13:55:14 +0530451 else
452 {
453 hddLog(LOG1,
454 "%s: remain_on_chan_ctx is NULL", __func__);
455 mutex_unlock(&pHddCtx->roc_lock);
456 }
457 return VOS_STATUS_SUCCESS;
Jeff Johnson32d95a32012-09-10 13:15:23 -0700458}
459
460int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
461{
462 int status = 0;
463 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
464
465 if(WLAN_HDD_P2P_GO != pAdapter->device_mode)
466 {
467 //Cancel Existing Remain On Channel
468 //If no action frame is pending
469 if( cfgState->remain_on_chan_ctx != NULL)
470 {
471 //Check whether Action Frame is pending or not
472 if( cfgState->buf == NULL)
473 {
474 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
475 }
476 else
477 {
Rashmi Ramannac7744532013-10-06 16:49:08 +0530478 hddLog(VOS_TRACE_LEVEL_DEBUG,
479 "Cannot Cancel Existing Remain on Channel");
Jeff Johnson32d95a32012-09-10 13:15:23 -0700480 status = -EBUSY;
481 }
482 }
483 }
484 return status;
485}
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530486void wlan_hdd_remain_on_chan_timeout(void *data)
487{
488 hdd_adapter_t *pAdapter = (hdd_adapter_t *)data;
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530489 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530490 hdd_cfg80211_state_t *cfgState;
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530491 hdd_context_t *pHddCtx;
Hanumantha Reddy Pothulada0fe362015-02-27 18:37:03 +0530492
493 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530494 {
Jeff Johnsonc135a9a2017-09-19 08:37:24 -0700495 hddLog( LOGE, FL("pAdapter is invalid %pK !!!"), pAdapter);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530496 return;
497 }
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530498 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530499 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530500 mutex_lock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530501 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530502
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530503 if (NULL == pRemainChanCtx)
504 {
505 hddLog( LOGE, FL("No Remain on channel is pending"));
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530506 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530507 return;
508 }
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +0530509
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530510 if ( TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
511 {
Abhishek Singhbd3041e2015-07-30 14:36:25 +0530512 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530513 hddLog( LOGE, FL("Cancellation already in progress"));
514 return;
515 }
516
517 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
518 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Abhishek Singh4892e962015-12-30 11:18:58 +0530519 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530520 hddLog( LOG1,"%s: Cancel Remain on Channel on timeout", __func__);
Abhishek Singh36b7c532015-03-13 15:50:54 +0530521 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
522 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530523 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
524 )
525 {
Deepthi Gowri70498252015-01-20 15:56:45 +0530526 if (eHAL_STATUS_SUCCESS !=
527 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter),
528 pAdapter->sessionId ))
529 {
530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
531 FL("Failed to Cancel Remain on Channel"));
532 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530533 }
Abhishek Singh36b7c532015-03-13 15:50:54 +0530534 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530535 {
Deepthi Gowri70498252015-01-20 15:56:45 +0530536 WLANSAP_CancelRemainOnChannel(
537 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530538 }
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +0530539
540 wlan_hdd_start_stop_tdls_source_timer(pHddCtx, eTDLS_SUPPORT_ENABLED);
541
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530542 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530543}
Jeff Johnson32d95a32012-09-10 13:15:23 -0700544
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530545static int wlan_hdd_p2p_start_remain_on_channel(
546 hdd_adapter_t *pAdapter)
547{
548 VOS_STATUS status = VOS_STATUS_SUCCESS;
549 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
550 hdd_adapter_t *pAdapter_temp;
551 v_BOOL_t isGoPresent = VOS_FALSE;
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530552 hdd_context_t *pHddCtx;
553 hdd_cfg80211_state_t *cfgState;
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530554 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530555 rem_on_channel_request_type_t request_type;
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530556 unsigned int duration;
557 v_U16_t hw_value;
558
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530559 int ret = 0;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530560
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530561 ENTER();
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530562 if (NULL == pAdapter)
563 {
564 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
565 "%s: Adapter is NULL",__func__);
566 return -EINVAL;
567 }
568 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
569 ret = wlan_hdd_validate_context(pHddCtx);
570 if (0 != ret)
571 {
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530572 return ret;
573 }
574 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
575 if (NULL == cfgState)
576 {
577 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
578 "%s: cfgState is not valid ",__func__);
579 return -EINVAL;
580 }
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530581 mutex_lock(&pHddCtx->roc_lock);
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530582 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530583 if ( pRemainChanCtx == NULL)
584 {
585 mutex_unlock(&pHddCtx->roc_lock);
586 hddLog( LOGE,
587 "%s-%d: pRemainChanCtx is NULL",
588 __func__, __LINE__);
589 return ret;
590 }
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +0530591 request_type = pRemainChanCtx->rem_on_chan_request;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530592 /* Initialize Remain on chan timer */
593 status = vos_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
594 VOS_TIMER_TYPE_SW,
595 wlan_hdd_remain_on_chan_timeout,
596 pAdapter);
597 if (status != VOS_STATUS_SUCCESS)
598 {
599 hddLog(VOS_TRACE_LEVEL_ERROR,
Ganesh Kondabattini02795ae2015-02-02 17:45:19 +0530600 FL("Not able to initalize remain_on_chan timer"));
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +0530601 hddLog( LOG1, FL(
Jeff Johnsonc135a9a2017-09-19 08:37:24 -0700602 "Freeing ROC ctx cfgState->remain_on_chan_ctx=%pK"),
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +0530603 cfgState->remain_on_chan_ctx);
Ganesh Kondabattini02795ae2015-02-02 17:45:19 +0530604 cfgState->remain_on_chan_ctx = NULL;
605 vos_mem_free(pRemainChanCtx);
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530606 mutex_unlock(&pHddCtx->roc_lock);
Ganesh Kondabattini02795ae2015-02-02 17:45:19 +0530607 return -EINVAL;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530608 }
Ganesh Kondabattini02795ae2015-02-02 17:45:19 +0530609
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530610 duration = pRemainChanCtx->duration;
611 hw_value = pRemainChanCtx->chan.hw_value;
612 mutex_unlock(&pHddCtx->roc_lock);
613
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530614 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
615 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
616 {
617 pAdapter_temp = pAdapterNode->pAdapter;
618 if (WLAN_HDD_P2P_GO == pAdapter_temp->device_mode)
619 {
620 isGoPresent = VOS_TRUE;
621 }
622 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
623 pAdapterNode = pNext;
624 }
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530625 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530626 //call sme API to start remain on channel.
627 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
628 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
629 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
630 )
631 {
632 tANI_U8 sessionId = pAdapter->sessionId;
633 //call sme API to start remain on channel.
634 if (eHAL_STATUS_SUCCESS != sme_RemainOnChannel(
635 WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530636 hw_value, duration,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530637 wlan_hdd_remain_on_channel_callback, pAdapter,
638 (tANI_U8)(request_type == REMAIN_ON_CHANNEL_REQUEST)? TRUE:FALSE))
639 {
640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
641 FL(" RemainOnChannel returned fail"));
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530642
643 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +0530644 pRemainChanCtx = cfgState->remain_on_chan_ctx;
645 hddLog( LOG1, FL(
Jeff Johnsonc135a9a2017-09-19 08:37:24 -0700646 "Freeing ROC ctx cfgState->remain_on_chan_ctx=%pK"),
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +0530647 cfgState->remain_on_chan_ctx);
648 if (pRemainChanCtx)
649 {
650 if(!VOS_IS_STATUS_SUCCESS(vos_timer_destroy
651 (&pRemainChanCtx->hdd_remain_on_chan_timer)))
652 {
653 hddLog( LOGE, FL(
654 "Failed to destroy hdd_remain_on_chan_timer"));
655 }
656 vos_mem_free(pRemainChanCtx);
657 cfgState->remain_on_chan_ctx = NULL;
658 }
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530659 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530660 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530661 return -EINVAL;
662 }
663
664 if( REMAIN_ON_CHANNEL_REQUEST == request_type)
665 {
666 if( eHAL_STATUS_SUCCESS != sme_RegisterMgmtFrame(
667 WLAN_HDD_GET_HAL_CTX(pAdapter),
668 sessionId, (SIR_MAC_MGMT_FRAME << 2) |
669 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 ))
670 {
671 hddLog(VOS_TRACE_LEVEL_ERROR, "sme_RegisterMgmtFrame returned fail");
672 }
673 }
674
675 }
Abhishek Singh36b7c532015-03-13 15:50:54 +0530676 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530677 {
678 //call sme API to start remain on channel.
679 if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
680 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530681 hw_value, duration,
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530682 wlan_hdd_remain_on_channel_callback, pAdapter ))
683
684 {
685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
686 "%s: WLANSAP_RemainOnChannel returned fail", __func__);
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530687 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +0530688 pRemainChanCtx = cfgState->remain_on_chan_ctx;
689 hddLog( LOG1, FL(
Jeff Johnsonc135a9a2017-09-19 08:37:24 -0700690 "Freeing ROC ctx cfgState->remain_on_chan_ctx=%pK"),
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +0530691 cfgState->remain_on_chan_ctx);
692 if (pRemainChanCtx)
693 {
694 if(!VOS_IS_STATUS_SUCCESS(vos_timer_destroy
695 (&pRemainChanCtx->hdd_remain_on_chan_timer)))
696 {
697 hddLog( LOGE, FL(
698 "Failed to destroy hdd_remain_on_chan_timer"));
699 }
700 vos_mem_free (pRemainChanCtx);
701 cfgState->remain_on_chan_ctx = NULL;
702 }
Deepthi Gowri6ccb1d42015-08-21 19:43:53 +0530703 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530704 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530705 return -EINVAL;
706 }
707
708
709 if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
710 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
711 (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
712 NULL, 0 ))
713 {
714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
715 "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
716 WLANSAP_CancelRemainOnChannel(
717 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Sushant Kaushik83392fa2015-05-05 17:44:40 +0530718 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530719 return -EINVAL;
720 }
721
722 }
723
Masti, Narayanraddi44b0db02015-12-22 11:54:35 +0530724 wlan_hdd_start_stop_tdls_source_timer(pHddCtx, eTDLS_SUPPORT_DISABLED);
725
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530726 pAdapter->is_roc_inprogress = TRUE;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530727 EXIT();
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530728 return 0;
729}
730
731
Jeff Johnson32d95a32012-09-10 13:15:23 -0700732static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
733 struct net_device *dev,
734 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700735#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson32d95a32012-09-10 13:15:23 -0700736 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700737#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700738 unsigned int duration, u64 *cookie,
739 rem_on_channel_request_type_t request_type )
740{
741 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
742 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
743 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530744 hdd_context_t *pHddCtx = NULL;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530745 VOS_STATUS checkReadyInd;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530746 hdd_adapter_t *pStaAdapter;
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530747 int status = 0;
748
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530749 ENTER();
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530750 if (NULL == pAdapter)
751 {
752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
753 "%s: HDD adapter is Null", __func__);
754 return -ENODEV;
755 }
756
757 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
758 status = wlan_hdd_validate_context(pHddCtx);
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530759 if (0 != status)
760 {
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530761 return status;
762 }
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530763
Jeff Johnson32d95a32012-09-10 13:15:23 -0700764 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
765 __func__,pAdapter->device_mode);
Yue Maf49ba872013-08-19 12:04:25 -0700766#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530767 hddLog(VOS_TRACE_LEVEL_INFO,
768 "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, dur %d,"
769 " request type %d, cookie %llu",
770 chan->hw_value, chan->center_freq, channel_type, duration,
771 request_type, *cookie);
Yue Maf49ba872013-08-19 12:04:25 -0700772#else
Rashmi Ramannac7744532013-10-06 16:49:08 +0530773 hddLog(VOS_TRACE_LEVEL_INFO,
774 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d"
775 " reuest type %d, cookie %llu", chan->hw_value, chan->center_freq,
776 duration, request_type, *cookie );
Yue Maf49ba872013-08-19 12:04:25 -0700777#endif
Jeff Johnson32d95a32012-09-10 13:15:23 -0700778 //Cancel existing remain On Channel if any
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530779 checkReadyInd = wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
780 if (VOS_STATUS_SUCCESS != checkReadyInd)
781 {
782 hddLog( LOGE, FL("Cancel Roc in progress"));
783 return -EBUSY;
784 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700785
Hanumanth Reddy Pothula80e3f8c2016-09-14 19:04:26 +0530786 if (TRUE == pHddCtx->btCoexModeSet)
787 {
788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
789 FL("BTCoex Mode operation in progress"));
790 return -EBUSY;
791 }
792
Sreelakshmi Konamki20ebed92016-10-27 12:13:30 +0530793 if(hdd_isConnectionInProgress((hdd_context_t *)pAdapter->pHddCtx, NULL,
794 NULL))
Jeff Johnson295189b2012-06-20 16:38:30 -0700795 {
796 hddLog( LOGE,
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +0530797 "%s: Connection is in progress", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700798 return -EBUSY;
799 }
800
Ganesh Kondabattinibdb415e2015-09-16 12:37:14 +0530801 mutex_lock(&pHddCtx->roc_lock);
802
Deepthi Gowri75664652016-09-08 17:44:35 +0530803 if (cfgState->remain_on_chan_ctx)
804 VOS_BUG(0);
805
Jeff Johnson295189b2012-06-20 16:38:30 -0700806 pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
807 if( NULL == pRemainChanCtx )
808 {
809 hddLog(VOS_TRACE_LEVEL_FATAL,
810 "%s: Not able to allocate memory for Channel context",
811 __func__);
Ganesh Kondabattinibdb415e2015-09-16 12:37:14 +0530812 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -0700813 return -ENOMEM;
814 }
815
Ganesh Kondabattini8ae1a072015-02-02 17:49:50 +0530816 vos_mem_zero(pRemainChanCtx, sizeof (hdd_remain_on_chan_ctx_t));
Jeff Johnson295189b2012-06-20 16:38:30 -0700817 vos_mem_copy( &pRemainChanCtx->chan, chan,
818 sizeof(struct ieee80211_channel) );
819
Yue Maf49ba872013-08-19 12:04:25 -0700820#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700821 pRemainChanCtx->chan_type = channel_type;
Yue Maf49ba872013-08-19 12:04:25 -0700822#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700823 pRemainChanCtx->duration = duration;
824 pRemainChanCtx->dev = dev;
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800825 *cookie = (uintptr_t) pRemainChanCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700826 pRemainChanCtx->cookie = *cookie;
827 pRemainChanCtx->rem_on_chan_request = request_type;
828 cfgState->remain_on_chan_ctx = pRemainChanCtx;
829 cfgState->current_freq = chan->center_freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530830 pRemainChanCtx->action_pkt_buff.freq = 0;
831 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
832 pRemainChanCtx->action_pkt_buff.frame_length = 0;
833 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = FALSE;
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +0530834 pRemainChanCtx->is_pending_roc_cancelled = FALSE;
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530835
Jeff Johnson295189b2012-06-20 16:38:30 -0700836 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
837
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530838 if (REMAIN_ON_CHANNEL_REQUEST == request_type)
Jeff Johnson295189b2012-06-20 16:38:30 -0700839 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530840 pStaAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
841 if((NULL != pStaAdapter)&&
842 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pStaAdapter)))
Sushant Kaushik298a8592014-12-09 17:34:07 +0530843 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530844 if (pAdapter->lastRocTs !=0 &&
845 ((vos_timer_get_system_time() - pAdapter->lastRocTs )
846 < pHddCtx->cfg_ini->gP2PListenDeferInterval))
Rashmi Ramannac7744532013-10-06 16:49:08 +0530847 {
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530848 if (pRemainChanCtx->duration > HDD_P2P_MAX_ROC_DURATION)
849 pRemainChanCtx->duration = HDD_P2P_MAX_ROC_DURATION;
Ganesh Kondabattinibdb415e2015-09-16 12:37:14 +0530850
851 mutex_unlock(&pHddCtx->roc_lock);
852
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530853 schedule_delayed_work(&pAdapter->roc_work,
854 msecs_to_jiffies(pHddCtx->cfg_ini->gP2PListenDeferInterval));
Jeff Johnsonc135a9a2017-09-19 08:37:24 -0700855 hddLog(VOS_TRACE_LEVEL_INFO, "Defer interval is %hu, pAdapter %pK",
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +0530856 pHddCtx->cfg_ini->gP2PListenDeferInterval, pAdapter);
857 return 0;
Rashmi Ramannac7744532013-10-06 16:49:08 +0530858 }
Madan Mohan Koyyalamudi35885912012-11-30 15:05:42 -0800859 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700860 }
Nirav Shah87cd0cb2013-12-28 21:22:09 +0530861
Ganesh Kondabattinibdb415e2015-09-16 12:37:14 +0530862 mutex_unlock(&pHddCtx->roc_lock);
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530863 status = wlan_hdd_p2p_start_remain_on_channel(pAdapter);
864
865 EXIT();
866 return status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700867}
868
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530869int __wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800870#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
871 struct wireless_dev *wdev,
872#else
Jeff Johnson295189b2012-06-20 16:38:30 -0700873 struct net_device *dev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800874#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700875 struct ieee80211_channel *chan,
Yue Maf49ba872013-08-19 12:04:25 -0700876#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson295189b2012-06-20 16:38:30 -0700877 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -0700878#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700879 unsigned int duration, u64 *cookie )
880{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800881#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
882 struct net_device *dev = wdev->netdev;
883#endif
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530884 hdd_adapter_t *pAdapter;
885 hdd_context_t *pHddCtx;
886 int ret = 0;
887
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530888 ENTER();
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530889 pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
890 if (NULL == pAdapter)
891 {
892 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
893 "%s: Adapter is NULL",__func__);
894 return -EINVAL;
895 }
896 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
897 ret = wlan_hdd_validate_context(pHddCtx);
898 if (0 != ret)
899 {
Mahesh A Saptasagar74088392015-02-05 17:22:09 +0530900 return ret;
901 }
Sushant Kaushik4b7cb302014-01-06 17:45:01 +0530902
903 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
904 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
905 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530906 ret = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -0700907 chan,
908#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
909 channel_type,
910#endif
911 duration, cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -0700912 REMAIN_ON_CHANNEL_REQUEST);
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530913 EXIT();
914 return ret;
Jeff Johnson295189b2012-06-20 16:38:30 -0700915}
916
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +0530917int wlan_hdd_cfg80211_remain_on_channel( struct wiphy *wiphy,
918#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
919 struct wireless_dev *wdev,
920#else
921 struct net_device *dev,
922#endif
923 struct ieee80211_channel *chan,
924#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
925 enum nl80211_channel_type channel_type,
926#endif
927 unsigned int duration, u64 *cookie )
928{
929 int ret;
930
931 vos_ssr_protect(__func__);
932 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
933#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
934 wdev,
935#else
936 dev,
937#endif
938 chan,
939#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
940 channel_type,
941#endif
942 duration, cookie);
943 vos_ssr_unprotect(__func__);
944
945 return ret;
946}
947
948
Jeff Johnson295189b2012-06-20 16:38:30 -0700949void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter )
950{
Kaushik, Sushant26402612014-05-03 16:56:06 +0530951 hdd_cfg80211_state_t *cfgState = NULL;
952 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Deepthi Gowri3124dcd2015-08-28 19:34:27 +0530953 hdd_context_t *pHddCtx;
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530954 VOS_STATUS status;
Kaushik, Sushant26402612014-05-03 16:56:06 +0530955 if (NULL == pAdapter)
956 {
957 hddLog(LOGE, FL("pAdapter is NULL"));
958 return;
959 }
Deepthi Gowri3124dcd2015-08-28 19:34:27 +0530960 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
961 if (NULL == pHddCtx)
962 {
963 hddLog(LOGE, FL("pHddCtx is NULL"));
964 return;
965 }
Kaushik, Sushant26402612014-05-03 16:56:06 +0530966 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri22d08752015-02-05 15:07:40 +0530967 pAdapter->startRocTs = vos_timer_get_system_time();
Deepthi Gowri3124dcd2015-08-28 19:34:27 +0530968 mutex_lock(&pHddCtx->roc_lock);
969 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700970 if( pRemainChanCtx != NULL )
971 {
Kaushik, Sushant78c3efe2014-05-13 10:29:34 +0530972 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
973 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
974 pAdapter->sessionId, pRemainChanCtx->duration));
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530975 //start timer for actual duration
976 status = vos_timer_start(&pRemainChanCtx->hdd_remain_on_chan_timer,
977 (pRemainChanCtx->duration));
978 if (VOS_STATUS_SUCCESS!=status)
979 {
980 hddLog( LOGE, FL("Remain on Channel timer start failed"));
981 }
982 if( REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700983 {
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -0800984 cfg80211_ready_on_channel(
985#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
986 pAdapter->dev->ieee80211_ptr,
987#else
988 pAdapter->dev,
989#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -0800990 (uintptr_t)pRemainChanCtx,
Yue Maf49ba872013-08-19 12:04:25 -0700991 &pRemainChanCtx->chan,
992#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
993 pRemainChanCtx->chan_type,
994#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700995 pRemainChanCtx->duration, GFP_KERNEL );
996 }
997#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Kaushik, Sushant7005e372014-04-08 11:36:54 +0530998 else if( OFF_CHANNEL_ACTION_TX == pRemainChanCtx->rem_on_chan_request)
Jeff Johnson295189b2012-06-20 16:38:30 -0700999 {
1000 complete(&pAdapter->offchannel_tx_event);
1001 }
1002#endif
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301003 // Check for cached action frame
1004 if ( pRemainChanCtx->action_pkt_buff.frame_length != 0 )
1005 {
Anand N Sunkad7bfc8e42015-07-29 09:59:45 +05301006#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
1007 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr,
1008 pRemainChanCtx->action_pkt_buff.freq, 0,
1009 pRemainChanCtx->action_pkt_buff.frame_ptr,
1010 pRemainChanCtx->action_pkt_buff.frame_length,
1011 NL80211_RXMGMT_FLAG_ANSWERED);
1012#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05301013 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr,
1014 pRemainChanCtx->action_pkt_buff.freq, 0,
1015 pRemainChanCtx->action_pkt_buff.frame_ptr,
1016 pRemainChanCtx->action_pkt_buff.frame_length,
1017 NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
1018#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301019 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr,
1020 pRemainChanCtx->action_pkt_buff.freq, 0,
1021 pRemainChanCtx->action_pkt_buff.frame_ptr,
1022 pRemainChanCtx->action_pkt_buff.frame_length,
1023 GFP_ATOMIC );
1024#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
1025 cfg80211_rx_mgmt( pAdapter->dev,
1026 pRemainChanCtx->action_pkt_buff.freq, 0,
1027 pRemainChanCtx->action_pkt_buff.frame_ptr,
1028 pRemainChanCtx->action_pkt_buff.frame_length,
1029 GFP_ATOMIC );
1030#else
1031 cfg80211_rx_mgmt( pAdapter->dev,
1032 pRemainChanCtx->action_pkt_buff.freq,
1033 pRemainChanCtx->action_pkt_buff.frame_ptr,
1034 pRemainChanCtx->action_pkt_buff.frame_length,
1035 GFP_ATOMIC );
1036#endif //LINUX_VERSION_CODE
1037 hddLog( LOGE, "%s: Sent cached action frame to supplicant", __func__);
1038 vos_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
1039 pRemainChanCtx->action_pkt_buff.frame_length = 0;
1040 pRemainChanCtx->action_pkt_buff.freq = 0;
1041 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
1042 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301043 hddLog( VOS_TRACE_LEVEL_INFO, "Ready on chan ind (cookie=%llu)",
1044 pRemainChanCtx->cookie);
Jeff Johnson295189b2012-06-20 16:38:30 -07001045 complete(&pAdapter->rem_on_chan_ready_event);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301046 if (TRUE == pRemainChanCtx->is_pending_roc_cancelled)
1047 {
Deepthi Gowri3124dcd2015-08-28 19:34:27 +05301048 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301049 /* since pRemainChanCtx->is_pending_roc_cancelled is
1050 * set, it means Cancel Reamain on channel command is
1051 * pending because remain on channel event was not
1052 * ready when cancel ROC was issued.So issue
1053 * cancel ROC now.
1054 */
1055 wlan_hdd_cancel_existing_remain_on_channel(pAdapter);
1056 }
Deepthi Gowri3124dcd2015-08-28 19:34:27 +05301057 else
1058 {
1059 mutex_unlock(&pHddCtx->roc_lock);
1060 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001061 }
1062 else
1063 {
Deepthi Gowri3124dcd2015-08-28 19:34:27 +05301064 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001065 hddLog( LOGW, "%s: No Pending Remain on channel Request", __func__);
1066 }
1067 return;
1068}
1069
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301070int __wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001071#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1072 struct wireless_dev *wdev,
1073#else
1074 struct net_device *dev,
1075#endif
1076 u64 cookie )
Jeff Johnson295189b2012-06-20 16:38:30 -07001077{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001078#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1079 struct net_device *dev = wdev->netdev;
1080#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001081 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07001082 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +05301083 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301084 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1085 int status;
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301086 u64 cookie_dummy;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301087
1088 ENTER();
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301089 cookie_dummy = cookie << 32;
1090 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1091 TRACE_CODE_HDD_CFG80211_CANCEL_REMAIN_ON_CHANNEL,
1092 pAdapter->sessionId, cookie_dummy));
1093 hddLog( LOG1, "Cancel remain on channel req");
Jeff Johnson295189b2012-06-20 16:38:30 -07001094
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301095 status = wlan_hdd_validate_context(pHddCtx);
1096
1097 if (0 != status)
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001098 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301099 return status;
Madan Mohan Koyyalamudib2c36892012-10-18 20:52:38 -07001100 }
Rashmi Ramannac7744532013-10-06 16:49:08 +05301101 hddLog( LOG1, "Cancel remain on channel req (cookie = %llu)", cookie);
1102
Jeff Johnson295189b2012-06-20 16:38:30 -07001103 /* FIXME cancel currently running remain on chan.
1104 * Need to check cookie and cancel accordingly
1105 */
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +05301106 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri8a76bdb2015-08-21 15:17:28 +05301107 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 if( (cfgState->remain_on_chan_ctx == NULL) ||
1109 (cfgState->remain_on_chan_ctx->cookie != cookie) )
1110 {
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301111 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001112 hddLog( LOGE,
1113 "%s: No Remain on channel pending with specified cookie value",
1114 __func__);
1115 return -EINVAL;
1116 }
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301117 if (TRUE != pRemainChanCtx->is_pending_roc_cancelled)
1118 {
Deepthi Gowri0e5c5d32015-03-30 13:52:53 +05301119 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301120 /* wait until remain on channel ready event received
1121 * for already issued remain on channel request */
1122 status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
1123 msecs_to_jiffies(WAIT_REM_CHAN_READY));
1124 if (0 >= status)
1125 {
1126 hddLog( LOGE,
1127 "%s: timeout waiting for remain on channel ready indication %d",
1128 __func__, status);
Swaroop Golti05f63402015-07-22 11:59:59 +05301129 mutex_lock(&pHddCtx->roc_lock);
1130 if (cfgState->remain_on_chan_ctx)
1131 cfgState->remain_on_chan_ctx->is_pending_roc_cancelled = TRUE;
1132 mutex_unlock(&pHddCtx->roc_lock);
Abhishek Singh837adf22015-10-01 17:37:37 +05301133 vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
1134 WLAN_LOG_INDICATOR_HOST_DRIVER,
1135 WLAN_LOG_REASON_HDD_TIME_OUT,
1136 FALSE, TRUE);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301137 return 0;
1138
1139 }
Deepthi Gowri0e5c5d32015-03-30 13:52:53 +05301140 mutex_lock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301141 }
1142 else
1143 {
1144 hddLog( LOG1, FL("Cancel ROC event is already pending, "
1145 "waiting for ready on channel indication.") );
Deepthi Gowri8f3c88f2014-12-22 14:38:14 +05301146 mutex_unlock(&pHddCtx->roc_lock);
Sushant Kaushik5ad9b7b2014-05-21 21:09:43 +05301147 return 0;
1148 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301149 if (NULL != cfgState->remain_on_chan_ctx)
1150 {
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +05301151 if(!VOS_IS_STATUS_SUCCESS(vos_timer_stop(
1152 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer)))
1153 {
1154 hddLog( LOGE, FL("Failed to stop hdd_remain_on_chan_timer"));
1155 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301156 if (TRUE == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress)
1157 {
Deepthi Gowri0e5c5d32015-03-30 13:52:53 +05301158 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301159 hddLog( LOG1,
1160 FL("ROC timer cancellation in progress,"
1161 " wait for completion"));
1162 status = wait_for_completion_interruptible_timeout(
1163 &pAdapter->cancel_rem_on_chan_var,
1164 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1165 if (0 >= status)
1166 {
1167 hddLog( LOGE,
1168 "%s:wait on cancel_rem_on_chan_var failed %d",
1169 __func__, status);
1170 }
1171 return 0;
1172 }
1173 else
1174 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = TRUE;
1175 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001176 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
Abhishek Singh4892e962015-12-30 11:18:58 +05301177 mutex_unlock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001178 /* Issue abort remain on chan request to sme.
1179 * The remain on channel callback will make sure the remain_on_chan
1180 * expired event is sent.
1181 */
Abhishek Singh36b7c532015-03-13 15:50:54 +05301182 if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
1183 ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
Deepthi Gowri70498252015-01-20 15:56:45 +05301184 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07001185 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301186 tANI_U8 sessionId = pAdapter->sessionId;
Deepthi Gowri70498252015-01-20 15:56:45 +05301187 if (eHAL_STATUS_SUCCESS !=
1188 sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
1189 sessionId ))
1190 {
1191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1192 FL("Failed to Cancel Remain on Channel"));
1193 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001194 }
Deepthi Gowri70498252015-01-20 15:56:45 +05301195 else if (WLAN_HDD_P2P_GO == pAdapter->device_mode)
Jeff Johnson295189b2012-06-20 16:38:30 -07001196 {
1197 WLANSAP_CancelRemainOnChannel(
Deepthi Gowri70498252015-01-20 15:56:45 +05301198 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07001199 }
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301200 else
Jeff Johnson295189b2012-06-20 16:38:30 -07001201 {
1202 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
1203 __func__, pAdapter->device_mode);
1204 return -EIO;
1205 }
c_hpothu7f63e882013-10-02 19:13:35 +05301206 status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
Jeff Johnson295189b2012-06-20 16:38:30 -07001207 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
c_hpothu7f63e882013-10-02 19:13:35 +05301208 if (0 >= status)
1209 {
1210 hddLog( LOGE,
1211 "%s:wait on cancel_rem_on_chan_var failed %d", __func__, status);
1212 }
Sushant Kaushik83392fa2015-05-05 17:44:40 +05301213 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301214
1215 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07001216 return 0;
1217}
1218
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301219int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001220#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301221 struct wireless_dev *wdev,
1222#else
1223 struct net_device *dev,
1224#endif
1225 u64 cookie )
1226{
1227 int ret;
1228
1229 vos_ssr_protect(__func__);
1230 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
1231#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1232 wdev,
1233#else
1234 dev,
1235#endif
1236 cookie);
1237 vos_ssr_unprotect(__func__);
1238
1239 return ret;
1240}
1241
1242
1243#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1244int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001245 struct ieee80211_channel *chan, bool offchan,
Yue Maf49ba872013-08-19 12:04:25 -07001246#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001247 enum nl80211_channel_type channel_type,
Yue Maf49ba872013-08-19 12:04:25 -07001248 bool channel_type_valid,
1249#endif
1250 unsigned int wait,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001251 const u8 *buf, size_t len, bool no_cck,
1252 bool dont_wait_for_ack, u64 *cookie )
1253#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301254int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001255 struct ieee80211_channel *chan, bool offchan,
1256 enum nl80211_channel_type channel_type,
1257 bool channel_type_valid, unsigned int wait,
1258 const u8 *buf, size_t len, bool no_cck,
1259 bool dont_wait_for_ack, u64 *cookie )
1260#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301261int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001262 struct ieee80211_channel *chan, bool offchan,
1263 enum nl80211_channel_type channel_type,
1264 bool channel_type_valid, unsigned int wait,
1265 const u8 *buf, size_t len, u64 *cookie )
1266#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301267int __wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
Jeff Johnson295189b2012-06-20 16:38:30 -07001268 struct ieee80211_channel *chan,
1269 enum nl80211_channel_type channel_type,
1270 bool channel_type_valid,
1271 const u8 *buf, size_t len, u64 *cookie )
1272#endif //LINUX_VERSION_CODE
1273{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001274#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1275 struct net_device *dev = wdev->netdev;
1276#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001277 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Nachiket Kukade78386c12018-03-28 15:06:47 +05301278 hdd_adapter_t *pGoAdapter;
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301279 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Deepthi Gowri7374e282015-08-26 19:22:58 +05301280 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301281 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +05301282 tANI_U8 type;
1283 tANI_U8 subType;
Mukul Sharma1e5d0b72014-07-01 19:22:21 +05301284 tActionFrmType actionFrmType = WLAN_HDD_ACTION_FRM_TYPE_MAX;
Jeff Johnsone7245742012-09-05 17:12:55 -07001285 bool noack = 0;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301286 int status;
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +05301287 uint32_t mgmt_hdr_len = sizeof(struct ieee80211_hdr_3addr);
Jeff Johnsone7245742012-09-05 17:12:55 -07001288
Jeff Johnson295189b2012-06-20 16:38:30 -07001289#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Deepthi Gowrie4c98032016-06-17 15:24:57 +05301290 uint8_t home_ch = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001291#endif
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301292
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301293 ENTER();
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +05301294
1295 if (len < mgmt_hdr_len + 1) {
1296 hddLog(VOS_TRACE_LEVEL_ERROR,"Invalid Length");
1297 return -EINVAL;
1298 }
1299
1300 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
1301 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
1302
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301303 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301304 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
1305 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301306 status = wlan_hdd_validate_context(pHddCtx);
1307
1308 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001309 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301310 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001311 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301312
c_hpothu7f63e882013-10-02 19:13:35 +05301313 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
1314 __func__, pAdapter->device_mode, type);
1315
1316
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001317 if ((type == SIR_MAC_MGMT_FRAME) &&
1318 (subType == SIR_MAC_MGMT_ACTION) &&
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +05301319 wlan_hdd_is_type_p2p_action(
1320 &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET], len - mgmt_hdr_len))
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001321 {
1322 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301323#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001324 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001325 {
1326 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
1327 actionFrmType);
1328 }
1329 else
1330 {
1331 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
1332 p2p_action_frame_type[actionFrmType]);
1333 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1334 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1335 {
1336 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1337 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001338 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001339 }
1340 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1341 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1342 {
1343 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1344 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
1345 " completed state");
1346 }
1347 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001348#endif
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301349 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001350
Jeff Johnsone7245742012-09-05 17:12:55 -07001351#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1352 noack = dont_wait_for_ack;
1353#endif
1354
Deepthi Gowri7374e282015-08-26 19:22:58 +05301355
Jeff Johnsone7245742012-09-05 17:12:55 -07001356 //If the wait is coming as 0 with off channel set
1357 //then set the wait to 200 ms
1358 if (offchan && !wait)
Deepthi Gowri22d08752015-02-05 15:07:40 +05301359 {
Ganesh Kondabattini7f6049c2015-02-20 20:39:05 +05301360 wait = ACTION_FRAME_DEFAULT_WAIT;
Deepthi Gowri7374e282015-08-26 19:22:58 +05301361 mutex_lock(&pHddCtx->roc_lock);
1362 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Ganesh Kondabattini7f6049c2015-02-20 20:39:05 +05301363 if (pRemainChanCtx)
1364 {
1365 tANI_U32 current_time = vos_timer_get_system_time();
1366 int remaining_roc_time = ((int) pRemainChanCtx->duration -
1367 (current_time - pAdapter->startRocTs));
1368 if ( remaining_roc_time > ACTION_FRAME_DEFAULT_WAIT)
1369 wait = remaining_roc_time;
1370 }
Deepthi Gowri7374e282015-08-26 19:22:58 +05301371 mutex_unlock(&pHddCtx->roc_lock);
Deepthi Gowri22d08752015-02-05 15:07:40 +05301372 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001373
Jeff Johnson295189b2012-06-20 16:38:30 -07001374 //Call sme API to send out a action frame.
1375 // OR can we send it directly through data path??
1376 // After tx completion send tx status back.
1377 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1378 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1379 )
1380 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001381 if (type == SIR_MAC_MGMT_FRAME)
1382 {
1383 if (subType == SIR_MAC_MGMT_PROBE_RSP)
1384 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301385 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -07001386 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301387 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001388 goto err_rem_channel;
1389 }
1390 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
1391 (subType == SIR_MAC_MGMT_DEAUTH))
1392 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001393 /* During EAP failure or P2P Group Remove supplicant
1394 * is sending del_station command to driver. From
1395 * del_station function, Driver will send deauth frame to
1396 * p2p client. No need to send disassoc frame from here.
1397 * so Drop the frame here and send tx indication back to
1398 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -07001399 */
1400 tANI_U8 dstMac[ETH_ALEN] = {0};
1401 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07001402 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001403 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -08001404 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001405 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08001406 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001407 goto err_rem_channel;
1408 }
1409 }
1410 }
1411
1412 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001413 {
1414 if ( !noack )
1415 {
1416 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1417 __func__);
1418 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1419 }
1420 else
1421 {
1422 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1423 __func__);
1424 return -EBUSY;
1425 }
1426 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001427
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301428 if( subType == SIR_MAC_MGMT_ACTION)
1429 {
1430 hddLog( LOG1, "Action frame tx request : %s",
1431 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1432 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001433
1434#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Deepthi Gowrie4c98032016-06-17 15:24:57 +05301435 if ( (( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1436 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )) &&
1437 (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)))
1438 {
1439 home_ch = pAdapter->sessionCtx.ap.operatingChannel;
1440 }
1441 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) &&
1442 (pAdapter->sessionCtx.station.conn_info.connState ==
1443 eConnectionState_Associated))
1444 {
1445 home_ch = pAdapter->sessionCtx.station.conn_info.operationChannel;
1446 }
Nachiket Kukade78386c12018-03-28 15:06:47 +05301447 else
1448 {
1449 pGoAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
1450 if (pGoAdapter && test_bit(SOFTAP_BSS_STARTED,
1451 &pGoAdapter->event_flags))
1452 home_ch = pGoAdapter->sessionCtx.ap.operatingChannel;
1453 }
1454
Jeff Johnson295189b2012-06-20 16:38:30 -07001455 //If GO adapter exists and operating on same frequency
1456 //then we will not request remain on channel
Deepthi Gowrie4c98032016-06-17 15:24:57 +05301457 if (ieee80211_frequency_to_channel(chan->center_freq) == home_ch)
Jeff Johnson295189b2012-06-20 16:38:30 -07001458 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301459 /* if GO exist and is not off channel
1460 * wait time should be zero.
1461 */
1462 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001463 goto send_frame;
1464 }
1465#endif
1466
1467#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1468 if( offchan && wait)
1469 {
1470 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301471 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001472 // In case of P2P Client mode if we are already
1473 // on the same channel then send the frame directly
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301474 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri7374e282015-08-26 19:22:58 +05301475 pRemainChanCtx = cfgState->remain_on_chan_ctx;
1476 if( (pRemainChanCtx != NULL) &&
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301477 (cfgState->current_freq == chan->center_freq)
1478 )
1479 {
1480 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
Deepthi Gowri7374e282015-08-26 19:22:58 +05301481 &pRemainChanCtx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301482 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301483 /* Some times FW is taking almost 500 msec for
1484 * full 15 retries, which leads to ROC expiration
1485 * by the time peer gets response from other peer.
1486 * Therefore as part of temporary fix , in host
1487 * ROC time is extended. For frames where we are
1488 * expecting response from peer , its extended by
1489 * 500 msec to make ROC wait time as 1 sec and
1490 * in other cases its extended by 300 msec to make
1491 * total ROC wait as 500 msec.
1492 * TODO: FW needs to fix as why 15 retry is taking
1493 * such long time.
1494 */
1495 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1496 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1497 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1498 wait = wait + ACTION_FRAME_RSP_WAIT;
1499 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1500 actionFrmType == WLAN_HDD_INVITATION_RESP )
1501 wait = wait + ACTION_FRAME_ACK_WAIT;
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +05301502
1503 if (!VOS_IS_STATUS_SUCCESS(vos_timer_stop(
1504 &pRemainChanCtx->hdd_remain_on_chan_timer)))
1505 {
1506 hddLog( LOGE, FL("Failed to stop hdd_remain_on_chan_timer"));
1507 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301508 status = vos_timer_start(
Deepthi Gowri7374e282015-08-26 19:22:58 +05301509 &pRemainChanCtx->hdd_remain_on_chan_timer,
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301510 wait);
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301511
1512 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301513
1514 hddLog(VOS_TRACE_LEVEL_INFO,
1515 "action frame: extending the wait time %u",
1516 wait);
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301517
1518 if ( status != VOS_STATUS_SUCCESS )
1519 {
1520 hddLog( LOGE, "Remain on Channel timer start failed");
1521 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301522 goto send_frame;
1523 }
1524 else
1525 {
1526 if ( TRUE ==
1527 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1528 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301529 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301530 hddLog(VOS_TRACE_LEVEL_INFO,
1531 "action frame tx: waiting for completion of ROC ");
1532
1533 status = wait_for_completion_interruptible_timeout(
1534 &pAdapter->cancel_rem_on_chan_var,
1535 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1536 if (0 >= status)
1537 {
1538 hddLog( LOGE,
1539 "%s:wait on cancel_rem_on_chan_var failed %d",
1540 __func__, status);
1541 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301542 goto bypass_lock;
vamsida0e5ab2013-12-26 14:33:27 +05301543 }
1544 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301545 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301546 mutex_unlock(&pHddCtx->roc_lock);
1547bypass_lock:
Rashmi Ramannac7744532013-10-06 16:49:08 +05301548 hddLog(VOS_TRACE_LEVEL_INFO,
1549 "action frame: Request ROC for wait time %u", wait);
Jeff Johnson295189b2012-06-20 16:38:30 -07001550 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001551 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001552 chan,
1553#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1554 channel_type,
1555#endif
1556 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301557 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001558
1559 if(0 != status)
1560 {
1561 if( (-EBUSY == status) &&
1562 (cfgState->current_freq == chan->center_freq) )
1563 {
1564 goto send_frame;
1565 }
1566 goto err_rem_channel;
1567 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001568 /* Wait for driver to be ready on the requested channel */
1569 status = wait_for_completion_interruptible_timeout(
1570 &pAdapter->offchannel_tx_event,
1571 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301572 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001573 {
c_hpothu7f63e882013-10-02 19:13:35 +05301574 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001575 goto err_rem_channel;
1576 }
1577 }
1578 else if ( offchan )
1579 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001580 /* Check before sending action frame
1581 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001582 if(NULL == cfgState->remain_on_chan_ctx)
1583 {
1584 goto err_rem_channel;
1585 }
1586 }
1587 send_frame:
1588#endif
1589
Jeff Johnsone7245742012-09-05 17:12:55 -07001590 if(!noack)
1591 {
1592 cfgState->buf = vos_mem_malloc( len ); //buf;
1593 if( cfgState->buf == NULL )
1594 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001595
Jeff Johnsone7245742012-09-05 17:12:55 -07001596 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001597
Jeff Johnsone7245742012-09-05 17:12:55 -07001598 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001599
Ganesh Kondabattinicdacf812015-09-01 12:36:09 +05301600 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001601#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001602 if( cfgState->remain_on_chan_ctx )
1603 {
1604 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1605 *cookie = cfgState->action_cookie;
1606 }
1607 else
1608 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001609#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001610 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001611 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001612#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001613 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001614#endif
Ganesh Kondabattinicdacf812015-09-01 12:36:09 +05301615 mutex_unlock(&pHddCtx->roc_lock);
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301616 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001617
1618 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001619 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1620 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001621 )
1622 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001623 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001624
Jeff Johnsone7245742012-09-05 17:12:55 -07001625 if ((type == SIR_MAC_MGMT_FRAME) &&
1626 (subType == SIR_MAC_MGMT_ACTION) &&
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +05301627 wlan_hdd_is_type_p2p_action(
1628 &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET],
1629 len - mgmt_hdr_len))
Jeff Johnson295189b2012-06-20 16:38:30 -07001630 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001631 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301632 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001633 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001634 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001635 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301636 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001637 }
1638 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1639 {
1640 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301641 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001642 }
1643 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301644
Jeff Johnson295189b2012-06-20 16:38:30 -07001645 if (eHAL_STATUS_SUCCESS !=
1646 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301647 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001648 {
1649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1650 "%s: sme_sendAction returned fail", __func__);
1651 goto err;
1652 }
1653 }
Deepthi Gowrie4c98032016-06-17 15:24:57 +05301654 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1655 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1656 )
Jeff Johnson295189b2012-06-20 16:38:30 -07001657 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001658 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001659 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001660 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 {
1662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1663 "%s: WLANSAP_SendAction returned fail", __func__);
1664 goto err;
1665 }
1666 }
1667
1668 return 0;
1669err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001670 if(!noack)
1671 {
1672 hdd_sendActionCnf( pAdapter, FALSE );
1673 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001674 return 0;
1675err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001676 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001677 cfg80211_mgmt_tx_status(
1678#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1679 pAdapter->dev->ieee80211_ptr,
1680#else
1681 pAdapter->dev,
1682#endif
1683 *cookie, buf, len, FALSE, GFP_KERNEL );
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301684 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07001685 return 0;
1686}
1687
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05301688#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
1689int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
1690 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
1691#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301692int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
1693 struct ieee80211_channel *chan, bool offchan,
1694#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1695 enum nl80211_channel_type channel_type,
1696 bool channel_type_valid,
1697#endif
1698 unsigned int wait,
1699 const u8 *buf, size_t len, bool no_cck,
1700 bool dont_wait_for_ack, u64 *cookie )
1701#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1702int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1703 struct ieee80211_channel *chan, bool offchan,
1704 enum nl80211_channel_type channel_type,
1705 bool channel_type_valid, unsigned int wait,
1706 const u8 *buf, size_t len, bool no_cck,
1707 bool dont_wait_for_ack, u64 *cookie )
1708#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1709int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1710 struct ieee80211_channel *chan, bool offchan,
1711 enum nl80211_channel_type channel_type,
1712 bool channel_type_valid, unsigned int wait,
1713 const u8 *buf, size_t len, u64 *cookie )
1714#else
1715int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1716 struct ieee80211_channel *chan,
1717 enum nl80211_channel_type channel_type,
1718 bool channel_type_valid,
1719 const u8 *buf, size_t len, u64 *cookie )
1720#endif //LINUX_VERSION_CODE
1721{
1722 int ret;
1723
1724 vos_ssr_protect(__func__);
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05301725#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
1726 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan,
1727 params->wait, params->buf, params->len,
1728 params->no_cck, params->dont_wait_for_ack,
1729 cookie);
1730#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301731 ret = __wlan_hdd_mgmt_tx(wiphy, wdev,
1732 chan, offchan,
1733#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1734 channel_type,
1735 channel_type_valid,
1736#endif
1737 wait,
1738 buf, len, no_cck,
1739 dont_wait_for_ack, cookie);
1740#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1741 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1742 channel_type, channel_type_valid, wait,
1743 buf, len, no_cck,
1744 dont_wait_for_ack, cookie);
1745#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1746 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1747 channel_type, channel_type_valid, wait,
1748 buf, len, cookie);
1749#else
1750 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, channel_type,
1751 channel_type_valid, buf, len, cookie);
1752#endif //LINUX_VERSION_CODE
1753 vos_ssr_unprotect(__func__);
1754
1755 return ret;
1756}
1757
Jeff Johnson295189b2012-06-20 16:38:30 -07001758#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001759#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301760int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001761 struct wireless_dev *wdev,
1762 u64 cookie)
1763{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301764 u64 cookie_dummy;
1765 cookie_dummy = cookie << 32;
1766 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1767 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001768 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1769}
1770#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301771int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001772 struct net_device *dev,
1773 u64 cookie)
1774{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301775 u64 cookie_dummy;
1776 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1777 cookie_dummy = cookie << 32;
1778 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1779 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1780 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001781 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1782}
1783#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001784#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001785
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301786#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1787#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1788int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1789 struct wireless_dev *wdev,
1790 u64 cookie)
1791{
1792 int ret;
1793
1794 vos_ssr_protect(__func__);
1795 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1796 vos_ssr_unprotect(__func__);
1797
1798 return ret;
1799}
1800#else
1801int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1802 struct net_device *dev,
1803 u64 cookie)
1804{
1805 int ret;
1806
1807 vos_ssr_protect(__func__);
1808 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie);
1809 vos_ssr_unprotect(__func__);
1810
1811 return ret;
1812}
1813#endif
1814#endif
1815
Jeff Johnson295189b2012-06-20 16:38:30 -07001816void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1817{
1818 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1819
Jeff Johnsone7245742012-09-05 17:12:55 -07001820 cfgState->actionFrmState = HDD_IDLE;
1821
Jeff Johnson295189b2012-06-20 16:38:30 -07001822 if( NULL == cfgState->buf )
1823 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001824 return;
1825 }
Deepthi Gowri108809c2016-06-16 18:04:24 +05301826 if (cfgState->is_go_neg_ack_received)
1827 {
1828 cfgState->is_go_neg_ack_received = 0;
1829 /* Sometimes its possible that host may receive the ack for GO
1830 * negotiation req after sending go negotaition confirmation,
1831 * in such case drop the ack received for the go negotiation
1832 * request, so that supplicant waits for the confirmation ack
1833 * from firmware.
1834 */
1835 hddLog( LOG1, FL("Drop the pending ack received in cfgState->actionFrmState %d"),
1836 cfgState->actionFrmState);
1837 return;
1838 }
1839
1840 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
Jeff Johnson295189b2012-06-20 16:38:30 -07001841
1842 /* If skb is NULL it means this packet was received on CFG80211 interface
1843 * else it was received on Monitor interface */
1844 if( cfgState->skb == NULL )
1845 {
1846 /*
1847 * buf is the same pointer it passed us to send. Since we are sending
1848 * it through control path, we use different buffers.
1849 * In case of mac80211, they just push it to the skb and pass the same
1850 * data while sending tx ack status.
1851 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001852 cfg80211_mgmt_tx_status(
1853#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1854 pAdapter->dev->ieee80211_ptr,
1855#else
1856 pAdapter->dev,
1857#endif
1858 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001859 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1860 vos_mem_free( cfgState->buf );
1861 cfgState->buf = NULL;
1862 }
1863 else
1864 {
1865 hdd_adapter_t* pMonAdapter =
1866 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1867 if( pMonAdapter == NULL )
1868 {
1869 hddLog( LOGE, "Not able to get Monitor Adapter");
1870 cfgState->skb = NULL;
1871 vos_mem_free( cfgState->buf );
1872 cfgState->buf = NULL;
1873 complete(&pAdapter->tx_action_cnf_event);
1874 return;
1875 }
1876 /* Send TX completion feedback over monitor interface. */
1877 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1878 cfgState->skb = NULL;
1879 vos_mem_free( cfgState->buf );
1880 cfgState->buf = NULL;
1881 /* Look for the next Mgmt packet to TX */
1882 hdd_mon_tx_mgmt_pkt(pAdapter);
1883 }
1884 complete(&pAdapter->tx_action_cnf_event);
1885}
1886
1887/**
1888 * hdd_setP2pNoa
1889 *
1890 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301891 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001892 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1893 *
1894 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301895 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001896 *
1897 *ASSUMPTIONS:
1898 *
1899 *
1900 *NOTE:
1901 *
1902 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301903 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001904 *
1905 * @return Status
1906 */
1907
1908int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1909{
1910 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1911 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1912 VOS_STATUS status = VOS_STATUS_SUCCESS;
1913 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001914 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001915 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001916 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001917
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001918 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001919 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301920 {
1921 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1922 "%s: strnchr failed to find delimeter",__func__);
1923 return -EINVAL;
1924 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001925 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001926 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1927 if (ret < 3)
1928 {
1929 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1930 "%s: P2P_SET GO NoA: fail to read param "
Sushant Kaushik87787972015-09-11 16:05:00 +05301931 "count=%d duration=%d interval=%d ",
kalikinkar dhara19d77182013-11-12 14:29:46 -08001932 __func__, count, start_time, duration);
1933 return -EINVAL;
1934 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001936 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001937 __func__, count, start_time, duration);
1938 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001939 /* PS Selection
1940 * Periodic NoA (2)
1941 * Single NOA (4)
1942 */
1943 NoA.opp_ps = 0;
1944 NoA.ctWindow = 0;
1945 if (count == 1)
1946 {
1947 NoA.duration = 0;
1948 NoA.single_noa_duration = duration;
1949 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1950 }
1951 else
1952 {
1953 NoA.duration = duration;
1954 NoA.single_noa_duration = 0;
1955 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1956 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001957 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001958 NoA.count = count;
1959 NoA.sessionid = pAdapter->sessionId;
1960
1961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1962 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1963 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001964 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001965 NoA.ctWindow, NoA.duration, NoA.interval,
1966 NoA.count, NoA.single_noa_duration,
1967 NoA.psSelection);
1968
1969 sme_p2pSetPs(hHal, &NoA);
1970 return status;
1971}
1972
1973/**
1974 * hdd_setP2pOpps
1975 *
1976 *FUNCTION:
1977 * This function is called from hdd_hostapd_ioctl function when Driver
1978 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1979 *
1980 *LOGIC:
1981 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1982 *
1983 *ASSUMPTIONS:
1984 *
1985 *
1986 *NOTE:
1987 *
1988 * @param dev Pointer to net device structure
1989 * @param command Pointer to command
1990 *
1991 * @return Status
1992 */
1993
1994int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
1995{
1996 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1997 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1998 VOS_STATUS status = VOS_STATUS_SUCCESS;
1999 tP2pPsConfig NoA;
2000 char *param;
2001 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08002002 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002003
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002004 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07002005 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05302006 {
2007 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2008 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002009 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05302010 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002011 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08002012 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
2013 if (ret < 3)
2014 {
2015 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2016 "%s: P2P_SET GO PS: fail to read param "
Sushant Kaushik87787972015-09-11 16:05:00 +05302017 " legacy_ps=%d opp_ps=%d ctwindow=%d ",
kalikinkar dhara19d77182013-11-12 14:29:46 -08002018 __func__, legacy_ps, opp_ps, ctwindow);
2019 return -EINVAL;
2020 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002021 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002022 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002023 __func__, legacy_ps, opp_ps, ctwindow);
2024
2025 /* PS Selection
2026 * Opportunistic Power Save (1)
2027 */
2028
2029 /* From wpa_cli user need to use separate command to set ctWindow and Opps
2030 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302031 * values are coming from wpa_supplicant as -1.
2032 * Example : User want to set ctWindow with 30 then wpa_cli command :
2033 * P2P_SET ctwindow 30
2034 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07002035 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302036 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002037 if (ctwindow != -1)
2038 {
2039
2040 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002041 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07002042 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
2043
2044 if (ctwindow != pAdapter->ctw)
2045 {
2046 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302047
Jeff Johnson295189b2012-06-20 16:38:30 -07002048 if(pAdapter->ops)
2049 {
2050 NoA.opp_ps = pAdapter->ops;
2051 NoA.ctWindow = pAdapter->ctw;
2052 NoA.duration = 0;
2053 NoA.single_noa_duration = 0;
2054 NoA.interval = 0;
2055 NoA.count = 0;
2056 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
2057 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302058
Jeff Johnson295189b2012-06-20 16:38:30 -07002059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2060 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
2061 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002062 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07002063 NoA.ctWindow, NoA.duration, NoA.interval,
2064 NoA.count, NoA.single_noa_duration,
2065 NoA.psSelection);
2066
2067 sme_p2pSetPs(hHal, &NoA);
2068 }
2069 return 0;
2070 }
2071 }
2072
2073 if (opp_ps != -1)
2074 {
2075 pAdapter->ops = opp_ps;
2076
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302077 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07002078 {
2079 NoA.opp_ps = opp_ps;
2080 NoA.ctWindow = pAdapter->ctw;
2081 NoA.duration = 0;
2082 NoA.single_noa_duration = 0;
2083 NoA.interval = 0;
2084 NoA.count = 0;
2085 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
2086 NoA.sessionid = pAdapter->sessionId;
2087
2088 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2089 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
2090 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002091 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07002092 NoA.ctWindow, NoA.duration, NoA.interval,
2093 NoA.count, NoA.single_noa_duration,
2094 NoA.psSelection);
2095
2096 sme_p2pSetPs(hHal, &NoA);
2097 }
2098 }
2099 return status;
2100}
2101
2102int hdd_setP2pPs( struct net_device *dev, void *msgData )
2103{
2104 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2105 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
2106 VOS_STATUS status = VOS_STATUS_SUCCESS;
2107 tP2pPsConfig NoA;
2108 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
2109
2110 NoA.opp_ps = pappNoA->opp_ps;
2111 NoA.ctWindow = pappNoA->ctWindow;
2112 NoA.duration = pappNoA->duration;
2113 NoA.interval = pappNoA->interval;
2114 NoA.count = pappNoA->count;
2115 NoA.single_noa_duration = pappNoA->single_noa_duration;
2116 NoA.psSelection = pappNoA->psSelection;
2117 NoA.sessionid = pAdapter->sessionId;
2118
2119 sme_p2pSetPs(hHal, &NoA);
2120 return status;
2121}
Jeff Johnson295189b2012-06-20 16:38:30 -07002122
2123static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
2124{
2125 tANI_U8 sessionType;
2126
2127 switch( type )
2128 {
2129 case NL80211_IFTYPE_AP:
2130 sessionType = WLAN_HDD_SOFTAP;
2131 break;
2132 case NL80211_IFTYPE_P2P_GO:
2133 sessionType = WLAN_HDD_P2P_GO;
2134 break;
2135 case NL80211_IFTYPE_P2P_CLIENT:
2136 sessionType = WLAN_HDD_P2P_CLIENT;
2137 break;
2138 case NL80211_IFTYPE_STATION:
2139 sessionType = WLAN_HDD_INFRA_STATION;
2140 break;
2141 case NL80211_IFTYPE_MONITOR:
2142 sessionType = WLAN_HDD_MONITOR;
2143 break;
2144 default:
2145 sessionType = WLAN_HDD_INFRA_STATION;
2146 break;
2147 }
2148
2149 return sessionType;
2150}
2151
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302152/**
2153 * hdd_close_all_adapters_per_mode() - close all adapters per mode
2154 * @hdd_ctx: pointer to hdd context
2155 * @mode: all adapters to be deleted in this mode
2156 *
2157 * Return: None
2158 */
2159static void
2160hdd_close_all_adapters_per_mode(hdd_context_t *hdd_ctx,
2161 uint32_t mode)
2162{
2163 hdd_adapter_t *adapter = hdd_get_adapter(hdd_ctx, mode);
2164
2165 while (adapter) {
2166 hdd_stop_adapter(hdd_ctx, adapter, VOS_TRUE);
2167 hdd_deinit_adapter(hdd_ctx, adapter, TRUE);
2168 hdd_close_adapter(hdd_ctx, adapter, VOS_TRUE);
2169
2170 adapter = hdd_get_adapter(hdd_ctx, mode);
2171 }
2172}
2173
2174static void wlan_hdd_create_p2p_adapter(hdd_context_t *hdd_ctx,
2175 tANI_U8 rtnl_held)
2176{
2177 hdd_adapter_t *p2p_adapter;
2178
2179 p2p_adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d",
2180 &hdd_ctx->p2pDeviceAddress.bytes[0],
2181 rtnl_held);
2182 if (!p2p_adapter)
2183 hddLog(LOGE,
2184 FL("Failed to do hdd_open_adapter for P2P Device Interface"));
2185}
2186
2187/**
2188 * wlan_hdd_add_monitor_check() - check for monitor intf and add if needed
2189 * @hdd_ctx: pointer to hdd context
2190 * @adapter: output pointer to hold created monitor adapter
2191 * @type: type of the interface
2192 * @name: name of the interface
2193 *
2194 * Return: 0 - on success
2195 * 1 - on failure
2196 */
2197static int
2198wlan_hdd_add_monitor_check(hdd_context_t *hdd_ctx, hdd_adapter_t **adapter,
2199 enum nl80211_iftype type, const char *name)
2200{
2201 hdd_adapter_t *sta_adapter;
2202 hdd_adapter_t *mon_adapter;
2203 uint32_t i;
2204
2205 *adapter = NULL;
2206
2207 /*
2208 * If add interface request is for monitor mode, then it can run in
2209 * parallel with only one station interface.
2210 * If there is no existing station interface return error
2211 */
2212 if (type != NL80211_IFTYPE_MONITOR)
2213 return 0;
2214
2215 if (!sme_IsFeatureSupportedByFW(STA_MONITOR_SCC)) {
2216 hddLog(LOGE, FL("No FW support for STA + MON SCC"));
2217 return -EINVAL;
2218 }
2219
2220 if (hdd_ctx->no_of_open_sessions[VOS_MONITOR_MODE]) {
2221 hddLog(VOS_TRACE_LEVEL_ERROR,
2222 "%s: monitor mode already exists, only one is possible",
2223 __func__);
2224
2225 return -EBUSY;
2226 }
2227
2228 /* Ensure there is only one station interface */
2229 if (hdd_ctx->no_of_open_sessions[VOS_STA_MODE] != 1) {
2230 hddLog(LOGE,
2231 FL("cannot add monitor mode, due to %u sta interfaces"),
2232 hdd_ctx->no_of_open_sessions[VOS_STA_MODE]);
2233
2234 return -EINVAL;
2235 }
2236
2237 sta_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
2238 if (!sta_adapter) {
2239 hddLog(LOGE, FL("No station adapter"));
2240 return -EINVAL;
2241 }
2242
2243 /* delete all the other interfaces */
2244 for (i = VOS_STA_SAP_MODE; i <= VOS_P2P_DEVICE; i++) {
2245 if (i == VOS_FTM_MODE || i == VOS_MONITOR_MODE)
2246 continue;
2247
2248 hdd_close_all_adapters_per_mode(hdd_ctx, i);
2249 }
2250
2251 mon_adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_MONITOR, name,
2252 wlan_hdd_get_intf_addr(hdd_ctx),
2253 VOS_TRUE);
2254 if (!mon_adapter) {
2255 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",
2256 __func__);
2257 wlan_hdd_create_p2p_adapter(hdd_ctx, TRUE);
2258 return -EINVAL;
2259 }
2260
2261 *adapter = mon_adapter;
2262 return 0;
2263}
2264
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302265#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2266static struct wireless_dev *
2267__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2268 const char *name,
2269 unsigned char name_assign_type,
2270 enum nl80211_iftype type,
2271 u32 *flags,
2272 struct vif_params *params)
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002273#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302274static struct net_device *
2275__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2276 const char *name,
2277 unsigned char name_assign_type,
2278 enum nl80211_iftype type,
2279 u32 *flags,
2280 struct vif_params *params)
Jeff Johnson295189b2012-06-20 16:38:30 -07002281#else
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302282static int
2283__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2284 const char *name,
2285 unsigned char name_assign_type,
2286 enum nl80211_iftype type,
2287 u32 *flags,
2288 struct vif_params *params)
Jeff Johnson295189b2012-06-20 16:38:30 -07002289#endif
2290{
2291 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302292 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05302293 hdd_scaninfo_t *pScanInfo = NULL;
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302294 int ret = 0;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302295
Jeff Johnson295189b2012-06-20 16:38:30 -07002296 ENTER();
2297
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302298 ret = wlan_hdd_validate_context(pHddCtx);
2299 if (0 != ret)
2300 {
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302301#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2302 return ERR_PTR(-EINVAL);
2303#else
2304 return -EAGAIN;
2305#endif
2306 }
2307
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302308 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2309 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05302310 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
2311 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
2312 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002313 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07002314 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002315 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05302316#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2317 return ERR_PTR(-EINVAL);
2318#else
2319 return -EAGAIN;
2320#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002321 }
2322
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302323 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
2324 hddLog(VOS_TRACE_LEVEL_ERROR,
2325 "%s: STA + MONITOR mode is in progress, cannot add new interface",
2326 __func__);
2327#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2328 return ERR_PTR(-EINVAL);
2329#else
2330 return -EBUSY;
2331#endif
2332 }
2333
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05302334 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2335 pScanInfo = &pHddCtx->scan_info;
2336 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
2337 (pHddCtx->scan_info.mScanPending))
2338 {
2339 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
2340 eCSR_SCAN_ABORT_DEFAULT);
2341 hddLog(VOS_TRACE_LEVEL_INFO,
2342 "%s: Abort Scan while adding virtual interface",__func__);
2343 }
2344
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302345 ret = wlan_hdd_add_monitor_check(pHddCtx, &pAdapter, type, name);
2346 if (ret) {
2347#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2348 return ERR_PTR(-EINVAL);
2349#else
2350 return ret;
2351#endif
2352 }
2353
2354 if (pAdapter)
2355 goto return_adapter;
2356
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05302357 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05302358 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
2359 ((NL80211_IFTYPE_P2P_GO == type) ||
2360 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07002361 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002362 /* Generate the P2P Interface Address. this address must be
2363 * different from the P2P Device Address.
2364 */
2365 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
2366 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302367 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07002368 wlan_hdd_get_session_type(type),
2369 name, p2pDeviceAddress.bytes,
2370 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07002371 }
2372 else
2373 {
2374 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
2375 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
2376 }
2377
2378 if( NULL == pAdapter)
2379 {
2380 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
2381#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05302382 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002383#else
2384 return -EINVAL;
2385#endif
2386 }
Masti, Narayanraddi41d82f02015-06-12 14:04:11 +05302387
Bala Venkatesh5c06a252018-07-12 16:08:04 +05302388 if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO ||
2389 type == NL80211_IFTYPE_AP)
Masti, Narayanraddi575ccc72015-08-17 18:04:57 +05302390 {
2391 /* Below function Notifies Mode change and
2392 * If p2p session is detected then invokes functionality to
2393 * Teardown TDLS links and disable offchannel if any. Since
2394 * TDLS is not supported in case of concurrency.
2395 */
2396 hddLog(LOG1, FL("Interface type = %d"), type);
2397 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
2398 }
Masti, Narayanraddi41d82f02015-06-12 14:04:11 +05302399
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302400return_adapter:
2401
Jeff Johnson295189b2012-06-20 16:38:30 -07002402 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002403#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2404 return pAdapter->dev->ieee80211_ptr;
2405#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07002406 return pAdapter->dev;
2407#else
2408 return 0;
2409#endif
2410}
2411
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302412#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2413struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2414 const char *name,
2415 unsigned char name_assign_type,
2416 enum nl80211_iftype type,
2417 struct vif_params *params)
2418{
2419 struct wireless_dev *wdev;
2420
2421 vos_ssr_protect(__func__);
2422 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
2423 type, &params->flags, params);
2424 vos_ssr_unprotect(__func__);
2425
2426 return wdev;
2427}
2428#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || \
2429 defined(WITH_BACKPORTS)
2430/**
2431 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
2432 * @wiphy: wiphy pointer
2433 * @name: User-visible name of the interface
2434 * @name_assign_type: the name of assign type of the netdev
2435 * @nl80211_iftype: (virtual) interface types
2436 * @flags: monitor mode configuration flags (not used)
2437 * @vif_params: virtual interface parameters (not used)
2438 *
2439 * Return: the pointer of wireless dev, otherwise ERR_PTR.
2440 */
2441struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2442 const char *name,
2443 unsigned char name_assign_type,
2444 enum nl80211_iftype type,
2445 u32 *flags,
2446 struct vif_params *params)
2447{
2448 struct wireless_dev *wdev;
2449
2450 vos_ssr_protect(__func__);
2451 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
2452 type, flags, params);
2453 vos_ssr_unprotect(__func__);
2454 return wdev;
2455
2456}
2457#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
2458/**
2459 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
2460 * @wiphy: wiphy pointer
2461 * @name: User-visible name of the interface
2462 * @nl80211_iftype: (virtual) interface types
2463 * @flags: monitor mode configuration flags (not used)
2464 * @vif_params: virtual interface parameters (not used)
2465 *
2466 * Return: the pointer of wireless dev, otherwise ERR_PTR.
2467 */
2468struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2469 const char *name,
2470 enum nl80211_iftype type,
2471 u32 *flags,
2472 struct vif_params *params)
2473{
2474 struct wireless_dev *wdev;
2475 unsigned char name_assign_type = 0;
2476
2477 vos_ssr_protect(__func__);
2478 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
2479 type, flags, params);
2480 vos_ssr_unprotect(__func__);
2481 return wdev;
2482
2483}
2484
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302485#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2486struct wireless_dev* wlan_hdd_add_virtual_intf(
2487 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
2488 u32 *flags, struct vif_params *params )
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302489{
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302490 struct wireless_dev *wdev;
2491 unsigned char name_assign_type = 0;
2492
2493 vos_ssr_protect(__func__);
2494 wdev = __wlan_hdd_add_virtual_intf(wiphy, (const char *)name,
2495 name_assign_type,
2496 type, flags, params);
2497 vos_ssr_unprotect(__func__);
2498 return wdev;
2499
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302500}
2501
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302502#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2503struct net_device* wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2504 char *name,
2505 enum nl80211_iftype type,
2506 u32 *flags,
2507 struct vif_params *params)
2508{
2509 struct net_device *ndev;
2510 unsigned char name_assign_type = 0;
2511
2512 vos_ssr_protect(__func__);
2513 ndev = __wlan_hdd_add_virtual_intf(wiphy, (const char *)name, name_assign_type,
2514 type, flags, params);
2515 vos_ssr_unprotect(__func__);
2516 return wdev;
2517
2518}
2519#else
2520int wlan_hdd_add_virtual_intf(struct wiphy *wiphy, char *name,
2521 enum nl80211_iftype type,
2522 u32 *flags, struct vif_params *params)
2523{
2524 int ret;
2525 unsigned char name_assign_type = 0;
2526
2527 vos_ssr_protect(__func__);
2528 ret = __wlan_hdd_add_virtual_intf(wiphy, (const char *)name, name_assign_type,
2529 type, flags, params);
2530 vos_ssr_unprotect(__func__);
2531
2532 return ret;
2533}
2534#endif
2535
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302536/**
2537 * hdd_delete_adapter() - stop and close adapter
2538 * @hdd_ctx: pointer to hdd context
2539 * @adapter: adapter to be deleted
2540 * @rtnl_held: rtnl lock held
2541 *
2542 * Rerurn: None
2543 */
2544static void
2545hdd_delete_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2546 tANI_U8 rtnl_held)
2547{
2548 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
2549 hdd_stop_adapter(hdd_ctx, adapter, VOS_TRUE);
Sourav Mohapatra47b07a02019-08-22 10:23:18 +05302550 hdd_deinit_adapter(hdd_ctx, adapter, TRUE);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302551 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
2552}
2553
2554/**
2555 * wlan_hdd_del_monitor() - delete monitor interface
2556 * @hdd_ctx: pointer to hdd context
2557 * @adapter: adapter to be deleted
2558 * @rtnl_held: rtnl lock held
2559 *
2560 * This function is invoked to delete monitor interface and also
2561 * station interface if needed.
2562 *
2563 * Return: None
2564 */
2565static void
2566wlan_hdd_del_monitor(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2567 tANI_U8 rtnl_held)
2568{
2569 hdd_adapter_t *monitor_adapter;
2570 bool delete_station = false;
2571
2572 monitor_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
2573 if (monitor_adapter != adapter)
2574 delete_station = true;
2575
2576 /* delete the monitor adapter and re-create the p2p-dev adapter */
2577 hdd_delete_adapter(hdd_ctx, monitor_adapter, rtnl_held);
2578
2579 wlan_hdd_create_p2p_adapter(hdd_ctx, rtnl_held);
2580
2581 if (delete_station)
2582 hdd_delete_adapter(hdd_ctx, adapter, rtnl_held);
2583}
2584
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302585#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2586int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
2587#else
2588int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002589#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002590{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002591#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2592 struct net_device *dev = wdev->netdev;
2593#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302594 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302595 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302596 int status;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302597
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302598 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07002599
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302600 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2601 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
2602 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302603 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302604 __func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002605
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302606 status = wlan_hdd_validate_context(pHddCtx);
2607
2608 if (0 != status)
2609 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302610 return status;
2611 }
2612
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302613 if (pHddCtx->concurrency_mode == VOS_STA_MON)
2614 wlan_hdd_del_monitor(pHddCtx, pAdapter, TRUE);
2615 else
2616 hdd_delete_adapter(pHddCtx, pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002617
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302618 EXIT();
2619 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002620}
2621
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302622#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2623int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
2624#else
2625int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
2626#endif
2627{
2628 int ret;
2629
2630 vos_ssr_protect(__func__);
2631#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2632 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
2633#else
2634 ret = __wlan_hdd_del_virtual_intf(wiphy, dev);
2635#endif
2636 vos_ssr_unprotect(__func__);
2637
2638 return ret;
2639}
2640
Jeff Johnson295189b2012-06-20 16:38:30 -07002641void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002642 tANI_U32 nFrameLength,
2643 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302644 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07002645{
2646 //Indicate a Frame over Monitor Intf.
2647 int rxstat;
2648 struct sk_buff *skb = NULL;
2649 int needed_headroom = 0;
2650 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
2651 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002652#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002653#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2654 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
2655#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002656#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002657 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
2658
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002659 if (NULL == pbFrames)
2660 {
2661 hddLog(LOGE, FL("NULL frame pointer"));
2662 return;
2663 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002664
2665 /* room for the radiotap header based on driver features
2666 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
2667 * RX flags.
2668 * */
2669 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
2670
2671 //alloc skb here
2672 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
2673 if (unlikely(NULL == skb))
2674 {
2675 hddLog( LOGW, FL("Unable to allocate skb"));
2676 return;
2677 }
2678 skb_reserve(skb, VPKT_SIZE_BUFFER);
2679 if (unlikely(skb_headroom(skb) < nFrameLength))
2680 {
2681 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2682 "HDD [%d]: Insufficient headroom, "
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07002683 "head[%pK], data[%pK], req[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07002684 __LINE__, skb->head, skb->data, nFrameLength);
2685 kfree_skb(skb);
2686 return ;
2687 }
2688 // actually push the data
2689 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
2690 /* prepend radiotap information */
2691 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
2692 {
2693 hddLog( LOGE, FL("Not Able Add Radio Tap"));
2694 //free skb
2695 kfree_skb(skb);
2696 return ;
2697 }
2698
2699 skb_reset_mac_header( skb );
2700 skb->dev = pMonAdapter->dev;
2701 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002702 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002703#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002704#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302705 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
2706 HDD_WAKE_LOCK_DURATION,
2707 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Jeff Johnsone7245742012-09-05 17:12:55 -07002708#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002709#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002710 rxstat = netif_rx_ni(skb);
2711 if( NET_RX_SUCCESS == rxstat )
2712 {
2713 hddLog( LOG1, FL("Success"));
2714 }
2715 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302716 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07002717
2718 return ;
2719}
2720
Abhishek Singh7d624e12015-11-30 14:29:27 +05302721void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302722 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07002723 tANI_U8* pbFrames,
2724 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05302725 tANI_U32 rxChan,
Abhishek Singh7d624e12015-11-30 14:29:27 +05302726 tANI_S8 rxRssi)
Jeff Johnson295189b2012-06-20 16:38:30 -07002727{
2728 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302729 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07002730 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002731 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07002732 tActionFrmType actionFrmType;
2733 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302734 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05302735 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302736 VOS_STATUS status;
2737 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002738
Agarwal Ashishae800dd2015-06-24 12:44:48 +05302739 hddLog(VOS_TRACE_LEVEL_INFO, FL("Frame Type = %d Frame Length = %d"),
2740 frameType, nFrameLength);
Jeff Johnson295189b2012-06-20 16:38:30 -07002741
2742 if (NULL == pAdapter)
2743 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002744 hddLog(LOGE, FL("pAdapter is NULL"));
2745 return;
2746 }
2747
2748 if (0 == nFrameLength)
2749 {
2750 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2751 return;
2752 }
2753
2754 if (NULL == pbFrames)
2755 {
2756 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002757 return;
2758 }
2759
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002760 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2761 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2762
2763 /* Get pAdapter from Destination mac address of the frame */
2764 if ((type == SIR_MAC_MGMT_FRAME) &&
Sreelakshmi Konamki14dccd22017-05-11 12:17:22 +05302765 (subType != SIR_MAC_MGMT_PROBE_REQ) &&
2766 !vos_is_macaddr_broadcast(
2767 (v_MACADDR_t *)&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]))
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002768 {
2769 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
2770 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
2771 if (NULL == pAdapter)
2772 {
2773 /* Under assumtion that we don't receive any action frame
2774 * with BCST as destination we dropping action frame
2775 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08002776 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
2777 MAC_ADDRESS_STR ,
2778 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
2779 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08002780 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002781 return;
2782 }
2783 }
2784
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002785
Jeff Johnson295189b2012-06-20 16:38:30 -07002786 if (NULL == pAdapter->dev)
2787 {
2788 hddLog( LOGE, FL("pAdapter->dev is NULL"));
2789 return;
2790 }
2791
2792 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2793 {
2794 hddLog( LOGE, FL("pAdapter has invalid magic"));
2795 return;
2796 }
2797
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302798 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2799 if (NULL == pHddCtx)
2800 {
2801 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
2802 return;
2803 }
2804
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002805 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2806 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07002807 {
2808 hdd_adapter_t *pMonAdapter =
2809 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
2810
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002811 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07002812 {
2813 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
2814 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
2815 pbFrames, frameType);
2816 return;
2817 }
2818 }
2819
2820 //Channel indicated may be wrong. TODO
2821 //Indicate an action frame.
2822 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
2823 {
2824 freq = ieee80211_channel_to_frequency( rxChan,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302825 HDD_NL80211_BAND_2GHZ);
Jeff Johnson295189b2012-06-20 16:38:30 -07002826 }
2827 else
2828 {
2829 freq = ieee80211_channel_to_frequency( rxChan,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302830 HDD_NL80211_BAND_5GHZ);
Jeff Johnson295189b2012-06-20 16:38:30 -07002831 }
2832
Jeff Johnsone7245742012-09-05 17:12:55 -07002833 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302834
2835 if ((type == SIR_MAC_MGMT_FRAME) &&
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002836 (subType == SIR_MAC_MGMT_ACTION))
Jeff Johnsone7245742012-09-05 17:12:55 -07002837 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002838 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
2839 {
2840 // public action frame
2841 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08002842 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 -08002843 // P2P action frames
2844 {
2845 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002846 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002847#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002848 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
2849 {
2850 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
2851 actionFrmType);
2852 }
2853 else
2854 {
2855 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
2856 p2p_action_frame_type[actionFrmType]);
2857 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
2858 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2859 {
2860 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
2861 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002862 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002863 }
2864 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
2865 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
2866 {
2867 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08002868 hddLog(LOGE,"[P2P State]GO negotiation progress to "
2869 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002870 }
2871 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
2872 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2873 {
2874 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
2875 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
2876 " completed state Autonomous GO formation");
2877 }
2878 }
2879#endif
Deepthi Gowri0637d592015-09-16 12:34:02 +05302880 mutex_lock(&pHddCtx->roc_lock);
2881 pRemainChanCtx = cfgState->remain_on_chan_ctx;
2882
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302883 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
2884 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
2885 {
2886 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
2887 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
2888 actionFrmType == WLAN_HDD_INVITATION_REQ ||
2889 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
2890 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
2891 {
2892 hddLog( LOG1, "Extend RoC timer on reception of"
2893 " Action Frame");
2894 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
2895 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
2896 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
2897 else
2898 extend_time = ACTION_FRAME_DEFAULT_WAIT;
2899 if (completion_done(&pAdapter->rem_on_chan_ready_event))
2900 {
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +05302901 if(!VOS_IS_STATUS_SUCCESS(vos_timer_stop(
2902 &pRemainChanCtx->hdd_remain_on_chan_timer)))
2903 {
2904 hddLog( LOGE, FL(
2905 "Failed to stop hdd_remain_on_chan_timer"));
2906 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302907 status = vos_timer_start(
2908 &pRemainChanCtx->hdd_remain_on_chan_timer,
2909 extend_time);
2910 if (status != VOS_STATUS_SUCCESS)
2911 {
2912 hddLog( LOGE, "ROC timer start failed");
2913 }
2914 }
2915 else
2916 {
2917 // Buffer Packet
2918 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2919 {
2920 pRemainChanCtx->action_pkt_buff.frame_length =
2921 nFrameLength;
2922 pRemainChanCtx->action_pkt_buff.freq = freq;
2923 pRemainChanCtx->action_pkt_buff.frame_ptr
2924 = vos_mem_malloc(nFrameLength);
2925 vos_mem_copy(
2926 pRemainChanCtx->action_pkt_buff.frame_ptr,
2927 pbFrames, nFrameLength);
2928 hddLog( LOGE,"%s:"
2929 "Action Pkt Cached successfully !!!", __func__);
2930 }
2931 else
2932 {
2933 hddLog( LOGE,"%s:"
2934 "Frames are pending. dropping frame !!!",
2935 __func__);
2936 }
Deepthi Gowri0637d592015-09-16 12:34:02 +05302937 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302938 return;
2939 }
2940 }
2941 }
2942 if (pRemainChanCtx != NULL &&
Deepthi Gowri12e2dae2015-12-07 17:32:09 +05302943 vos_timer_is_initialized(
2944 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) &&
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302945 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2946 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2947 hddLog( LOG1, "%s:"
2948 "Rcvd action frame after timer expired ", __func__);
2949
Deepthi Gowri0637d592015-09-16 12:34:02 +05302950 mutex_unlock(&pHddCtx->roc_lock);
2951
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302952 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2953 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2954 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2955 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2956 {
Deepthi Gowri0637d592015-09-16 12:34:02 +05302957 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302958 __func__);
Deepthi Gowri108809c2016-06-16 18:04:24 +05302959 cfgState->is_go_neg_ack_received = 1;
2960
Deepthi Gowri0637d592015-09-16 12:34:02 +05302961 hdd_sendActionCnf(pAdapter, TRUE);
2962 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002963 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002964#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002965 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 -07002966 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002967 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302968 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002969 MAC_ADDR_ARRAY(mac),rxRssi);
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302970
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002971 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2972 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002973 }
2974#endif
2975 }
Kaushik, Sushant507a8612014-10-21 17:00:55 +05302976
2977 pScanInfo = &pHddCtx->scan_info;
2978 if ((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2979 {
2980 hddLog(LOGE,"Action frame received when Scanning is in"
2981 " progress. Abort Scan.");
2982 hdd_abort_mac_scan(pAdapter->pHddCtx,
2983 pScanInfo->sessionId,
2984 eCSR_SCAN_ABORT_DEFAULT);
2985 }
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302986
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002987 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
2988 {
2989 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
2990 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
2991 {
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302992 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] Action type[%d] <--- OTA",
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002993 actionFrmType);
2994 }
2995 else
2996 {
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302997 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] %s <--- OTA",
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002998 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002999 }
Abhishek Singh888420b2016-01-06 12:28:03 +05303000 vos_tdls_tx_rx_mgmt_event(SIR_MAC_ACTION_TDLS,
3001 SIR_MAC_ACTION_RX, SIR_MAC_MGMT_ACTION,
3002 actionFrmType, &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07003003 }
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05303004
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07003005 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
3006 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
3007 {
Kumar Anand82c009f2014-05-29 00:29:42 -07003008 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
3009 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07003010 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003011 }
3012
Jeff Johnson295189b2012-06-20 16:38:30 -07003013 //Indicate Frame Over Normal Interface
3014 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
Anand N Sunkad7bfc8e42015-07-29 09:59:45 +05303015#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
yeshwanth sriram guntukabbdd77c2017-05-02 12:49:53 +05303016 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, rxRssi * 100, pbFrames,
Anand N Sunkad7bfc8e42015-07-29 09:59:45 +05303017 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED);
3018#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
yeshwanth sriram guntukabbdd77c2017-05-02 12:49:53 +05303019 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, rxRssi * 100, pbFrames,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303020 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
3021#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
yeshwanth sriram guntukabbdd77c2017-05-02 12:49:53 +05303022 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, rxRssi * 100,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003023 pbFrames, nFrameLength,
3024 GFP_ATOMIC );
3025#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
yeshwanth sriram guntukabbdd77c2017-05-02 12:49:53 +05303026 cfg80211_rx_mgmt( pAdapter->dev, freq, rxRssi * 100,
Jeff Johnson295189b2012-06-20 16:38:30 -07003027 pbFrames, nFrameLength,
3028 GFP_ATOMIC );
3029#else
3030 cfg80211_rx_mgmt( pAdapter->dev, freq,
3031 pbFrames, nFrameLength,
3032 GFP_ATOMIC );
3033#endif //LINUX_VERSION_CODE
3034}
3035
3036/*
3037 * ieee80211_add_rx_radiotap_header - add radiotap header
3038 */
3039static int hdd_wlan_add_rx_radiotap_hdr (
3040 struct sk_buff *skb, int rtap_len, int flag )
3041{
3042 u8 rtap_temp[20] = {0};
3043 struct ieee80211_radiotap_header *rthdr;
3044 unsigned char *pos;
3045 u16 rx_flags = 0;
3046
3047 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
3048
3049 /* radiotap header, set always present flags */
3050 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
3051 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
3052 rthdr->it_len = cpu_to_le16(rtap_len);
3053
3054 pos = (unsigned char *) (rthdr + 1);
3055
3056 /* the order of the following fields is important */
3057
3058 /* IEEE80211_RADIOTAP_FLAGS */
3059 *pos = 0;
3060 pos++;
3061
3062 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
3063 /* ensure 2 byte alignment for the 2 byte field as required */
3064 if ((pos - (u8 *)rthdr) & 1)
3065 pos++;
3066 put_unaligned_le16(rx_flags, pos);
3067 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05303068
Jeff Johnson295189b2012-06-20 16:38:30 -07003069 // actually push the data
3070 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
3071
3072 return 0;
3073}
3074
3075static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
3076 hdd_cfg80211_state_t* cfgState,
3077 tANI_BOOLEAN actionSendSuccess )
3078{
3079 struct ieee80211_radiotap_header *rthdr;
3080 unsigned char *pos;
3081 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003082#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003083#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3084 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
3085#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003086#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003087
3088 /* 2 Byte for TX flags and 1 Byte for Retry count */
3089 u32 rtHdrLen = sizeof(*rthdr) + 3;
3090
3091 u8 *data;
3092
3093 /* We have to return skb with Data starting with MAC header. We have
3094 * copied SKB data starting with MAC header to cfgState->buf. We will pull
3095 * entire skb->len from skb and then we will push cfgState->buf to skb
3096 * */
3097 if( NULL == skb_pull(skb, skb->len) )
3098 {
3099 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
3100 kfree_skb(cfgState->skb);
3101 return;
3102 }
3103
3104 data = skb_push( skb, cfgState->len );
3105
3106 if (data == NULL)
3107 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08003108 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003109 kfree_skb( cfgState->skb );
3110 return;
3111 }
3112
3113 memcpy( data, cfgState->buf, cfgState->len );
3114
3115 /* send frame to monitor interfaces now */
3116 if( skb_headroom(skb) < rtHdrLen )
3117 {
3118 hddLog( LOGE, FL("No headroom for rtap header"));
3119 kfree_skb(cfgState->skb);
3120 return;
3121 }
3122
3123 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
3124
3125 memset( rthdr, 0, rtHdrLen );
3126 rthdr->it_len = cpu_to_le16( rtHdrLen );
3127 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
3128 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
3129 );
3130
3131 pos = (unsigned char *)( rthdr+1 );
3132
3133 // Fill TX flags
3134 *pos = actionSendSuccess;
3135 pos += 2;
3136
3137 // Fill retry count
3138 *pos = 0;
3139 pos++;
3140
3141 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07003142 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003143 skb->pkt_type = PACKET_OTHERHOST;
3144 skb->protocol = htons(ETH_P_802_2);
3145 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003146#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003147#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05303148 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
3149 HDD_WAKE_LOCK_DURATION,
3150 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Jeff Johnsone7245742012-09-05 17:12:55 -07003151#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003153 if (in_interrupt())
3154 netif_rx( skb );
3155 else
3156 netif_rx_ni( skb );
3157
3158 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05303159 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05303160 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003161
3162}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05303163
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +05303164void __hdd_p2p_roc_work_queue(struct work_struct *work)
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05303165{
3166 hdd_adapter_t *pAdapter = container_of(to_delayed_work(work), hdd_adapter_t, roc_work);
3167 hddLog( VOS_TRACE_LEVEL_INFO, FL("%s: "), __func__);
3168 wlan_hdd_p2p_start_remain_on_channel(pAdapter);
3169 return;
3170}
3171
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +05303172void hdd_p2p_roc_work_queue(struct work_struct *work)
3173{
3174 vos_ssr_protect(__func__);
3175 __hdd_p2p_roc_work_queue(work);
3176 vos_ssr_unprotect(__func__);
3177 return;
3178}