blob: 3b1b38f418c7c324f5d24bdf7d8563a2e4a53f3e [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Abhinav Kumar8eed0362019-08-05 14:26:07 +05302 * Copyright (c) 2012-2019 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
Abhinav Kumar8eed0362019-08-05 14:26:07 +05301292 eHalStatus hal_status;
Kaushik, Sushantb1ed0f42014-07-01 18:26:31 +05301293
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301294 ENTER();
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +05301295
1296 if (len < mgmt_hdr_len + 1) {
1297 hddLog(VOS_TRACE_LEVEL_ERROR,"Invalid Length");
1298 return -EINVAL;
1299 }
1300
1301 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
1302 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
1303
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301304 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301305 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
1306 pAdapter->device_mode ));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301307 status = wlan_hdd_validate_context(pHddCtx);
1308
1309 if (0 != status)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001310 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301311 return status;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -08001312 }
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05301313
c_hpothu7f63e882013-10-02 19:13:35 +05301314 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d type: %d",
1315 __func__, pAdapter->device_mode, type);
1316
Abhinav Kumar8eed0362019-08-05 14:26:07 +05301317 /* When frame to be transmitted is auth mgmt, then trigger
1318 * sme_send_mgmt_tx to send auth frame.
1319 */
1320 if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) &&
1321 (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_AUTH)) {
1322 hal_status = sme_send_mgmt_tx(WLAN_HDD_GET_HAL_CTX(pAdapter),
1323 pAdapter->sessionId, buf, len);
1324 if (HAL_STATUS_SUCCESS(hal_status))
1325 return 0;
1326 else
1327 return -EINVAL;
1328 }
c_hpothu7f63e882013-10-02 19:13:35 +05301329
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001330 if ((type == SIR_MAC_MGMT_FRAME) &&
1331 (subType == SIR_MAC_MGMT_ACTION) &&
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +05301332 wlan_hdd_is_type_p2p_action(
1333 &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET], len - mgmt_hdr_len))
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001334 {
1335 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301336#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001337 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001338 {
1339 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
1340 actionFrmType);
1341 }
1342 else
1343 {
1344 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
1345 p2p_action_frame_type[actionFrmType]);
1346 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
1347 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
1348 {
1349 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
1350 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08001351 "GO negotiation progress state");
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001352 }
1353 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1354 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
1355 {
1356 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
1357 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
1358 " completed state");
1359 }
1360 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001361#endif
Kaushik, Sushant731e8942014-09-08 11:59:19 +05301362 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07001363
Jeff Johnsone7245742012-09-05 17:12:55 -07001364#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1365 noack = dont_wait_for_ack;
1366#endif
1367
Deepthi Gowri7374e282015-08-26 19:22:58 +05301368
Jeff Johnsone7245742012-09-05 17:12:55 -07001369 //If the wait is coming as 0 with off channel set
1370 //then set the wait to 200 ms
1371 if (offchan && !wait)
Deepthi Gowri22d08752015-02-05 15:07:40 +05301372 {
Ganesh Kondabattini7f6049c2015-02-20 20:39:05 +05301373 wait = ACTION_FRAME_DEFAULT_WAIT;
Deepthi Gowri7374e282015-08-26 19:22:58 +05301374 mutex_lock(&pHddCtx->roc_lock);
1375 pRemainChanCtx = cfgState->remain_on_chan_ctx;
Ganesh Kondabattini7f6049c2015-02-20 20:39:05 +05301376 if (pRemainChanCtx)
1377 {
1378 tANI_U32 current_time = vos_timer_get_system_time();
1379 int remaining_roc_time = ((int) pRemainChanCtx->duration -
1380 (current_time - pAdapter->startRocTs));
1381 if ( remaining_roc_time > ACTION_FRAME_DEFAULT_WAIT)
1382 wait = remaining_roc_time;
1383 }
Deepthi Gowri7374e282015-08-26 19:22:58 +05301384 mutex_unlock(&pHddCtx->roc_lock);
Deepthi Gowri22d08752015-02-05 15:07:40 +05301385 }
Jeff Johnsone7245742012-09-05 17:12:55 -07001386
Jeff Johnson295189b2012-06-20 16:38:30 -07001387 //Call sme API to send out a action frame.
1388 // OR can we send it directly through data path??
1389 // After tx completion send tx status back.
1390 if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1391 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1392 )
1393 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001394 if (type == SIR_MAC_MGMT_FRAME)
1395 {
1396 if (subType == SIR_MAC_MGMT_PROBE_RSP)
1397 {
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301398 /* Drop Probe response recieved from supplicant, as for GO and
Jeff Johnson295189b2012-06-20 16:38:30 -07001399 SAP PE itself sends probe response
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301400 */
Jeff Johnson295189b2012-06-20 16:38:30 -07001401 goto err_rem_channel;
1402 }
1403 else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
1404 (subType == SIR_MAC_MGMT_DEAUTH))
1405 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001406 /* During EAP failure or P2P Group Remove supplicant
1407 * is sending del_station command to driver. From
1408 * del_station function, Driver will send deauth frame to
1409 * p2p client. No need to send disassoc frame from here.
1410 * so Drop the frame here and send tx indication back to
1411 * supplicant.
Jeff Johnson295189b2012-06-20 16:38:30 -07001412 */
1413 tANI_U8 dstMac[ETH_ALEN] = {0};
1414 memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
Jeff Johnsone7245742012-09-05 17:12:55 -07001415 hddLog(VOS_TRACE_LEVEL_INFO,
Jeff Johnson295189b2012-06-20 16:38:30 -07001416 "%s: Deauth/Disassoc received for STA:"
Arif Hussain24bafea2013-11-15 15:10:03 -08001417 MAC_ADDRESS_STR,
Jeff Johnsone7245742012-09-05 17:12:55 -07001418 __func__,
Arif Hussain24bafea2013-11-15 15:10:03 -08001419 MAC_ADDR_ARRAY(dstMac));
Jeff Johnson295189b2012-06-20 16:38:30 -07001420 goto err_rem_channel;
1421 }
1422 }
1423 }
1424
1425 if( NULL != cfgState->buf )
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001426 {
1427 if ( !noack )
1428 {
1429 hddLog( LOGE, "(%s):Previous P2P Action frame packet pending",
1430 __func__);
1431 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1432 }
1433 else
1434 {
1435 hddLog( LOGE, "(%s):Pending Action frame packet return EBUSY",
1436 __func__);
1437 return -EBUSY;
1438 }
1439 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001440
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301441 if( subType == SIR_MAC_MGMT_ACTION)
1442 {
1443 hddLog( LOG1, "Action frame tx request : %s",
1444 hdd_getActionString(buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1445 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001446
1447#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Deepthi Gowrie4c98032016-06-17 15:24:57 +05301448 if ( (( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
1449 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )) &&
1450 (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags)))
1451 {
1452 home_ch = pAdapter->sessionCtx.ap.operatingChannel;
1453 }
1454 else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) &&
1455 (pAdapter->sessionCtx.station.conn_info.connState ==
1456 eConnectionState_Associated))
1457 {
1458 home_ch = pAdapter->sessionCtx.station.conn_info.operationChannel;
1459 }
Nachiket Kukade78386c12018-03-28 15:06:47 +05301460 else
1461 {
1462 pGoAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_GO);
1463 if (pGoAdapter && test_bit(SOFTAP_BSS_STARTED,
1464 &pGoAdapter->event_flags))
1465 home_ch = pGoAdapter->sessionCtx.ap.operatingChannel;
1466 }
1467
Jeff Johnson295189b2012-06-20 16:38:30 -07001468 //If GO adapter exists and operating on same frequency
1469 //then we will not request remain on channel
Deepthi Gowrie4c98032016-06-17 15:24:57 +05301470 if (ieee80211_frequency_to_channel(chan->center_freq) == home_ch)
Jeff Johnson295189b2012-06-20 16:38:30 -07001471 {
Kaushik, Sushant39bdbe22014-05-23 10:39:15 +05301472 /* if GO exist and is not off channel
1473 * wait time should be zero.
1474 */
1475 wait = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001476 goto send_frame;
1477 }
1478#endif
1479
1480#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1481 if( offchan && wait)
1482 {
1483 int status;
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301484 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
Jeff Johnson295189b2012-06-20 16:38:30 -07001485 // In case of P2P Client mode if we are already
1486 // on the same channel then send the frame directly
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301487 mutex_lock(&pHddCtx->roc_lock);
Deepthi Gowri7374e282015-08-26 19:22:58 +05301488 pRemainChanCtx = cfgState->remain_on_chan_ctx;
1489 if( (pRemainChanCtx != NULL) &&
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301490 (cfgState->current_freq == chan->center_freq)
1491 )
1492 {
1493 if ( VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(
Deepthi Gowri7374e282015-08-26 19:22:58 +05301494 &pRemainChanCtx->hdd_remain_on_chan_timer) )
vamsida0e5ab2013-12-26 14:33:27 +05301495 {
Sushant Kaushik22257d62014-05-20 19:27:07 +05301496 /* Some times FW is taking almost 500 msec for
1497 * full 15 retries, which leads to ROC expiration
1498 * by the time peer gets response from other peer.
1499 * Therefore as part of temporary fix , in host
1500 * ROC time is extended. For frames where we are
1501 * expecting response from peer , its extended by
1502 * 500 msec to make ROC wait time as 1 sec and
1503 * in other cases its extended by 300 msec to make
1504 * total ROC wait as 500 msec.
1505 * TODO: FW needs to fix as why 15 retry is taking
1506 * such long time.
1507 */
1508 if ( actionFrmType == WLAN_HDD_INVITATION_REQ ||
1509 actionFrmType == WLAN_HDD_GO_NEG_REQ ||
1510 actionFrmType == WLAN_HDD_GO_NEG_RESP )
1511 wait = wait + ACTION_FRAME_RSP_WAIT;
1512 else if ( actionFrmType == WLAN_HDD_GO_NEG_CNF ||
1513 actionFrmType == WLAN_HDD_INVITATION_RESP )
1514 wait = wait + ACTION_FRAME_ACK_WAIT;
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +05301515
1516 if (!VOS_IS_STATUS_SUCCESS(vos_timer_stop(
1517 &pRemainChanCtx->hdd_remain_on_chan_timer)))
1518 {
1519 hddLog( LOGE, FL("Failed to stop hdd_remain_on_chan_timer"));
1520 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301521 status = vos_timer_start(
Deepthi Gowri7374e282015-08-26 19:22:58 +05301522 &pRemainChanCtx->hdd_remain_on_chan_timer,
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301523 wait);
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301524
1525 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301526
1527 hddLog(VOS_TRACE_LEVEL_INFO,
1528 "action frame: extending the wait time %u",
1529 wait);
Hema Aparna Medicharla8bb6f782015-03-09 12:35:05 +05301530
1531 if ( status != VOS_STATUS_SUCCESS )
1532 {
1533 hddLog( LOGE, "Remain on Channel timer start failed");
1534 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301535 goto send_frame;
1536 }
1537 else
1538 {
1539 if ( TRUE ==
1540 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress )
1541 {
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301542 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301543 hddLog(VOS_TRACE_LEVEL_INFO,
1544 "action frame tx: waiting for completion of ROC ");
1545
1546 status = wait_for_completion_interruptible_timeout(
1547 &pAdapter->cancel_rem_on_chan_var,
1548 msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
1549 if (0 >= status)
1550 {
1551 hddLog( LOGE,
1552 "%s:wait on cancel_rem_on_chan_var failed %d",
1553 __func__, status);
1554 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301555 goto bypass_lock;
vamsida0e5ab2013-12-26 14:33:27 +05301556 }
1557 }
Edhar, Mahesh Kumar9b223db2013-11-28 11:30:01 +05301558 }
Mahesh A Saptasagar5c032042015-01-08 14:56:33 +05301559 mutex_unlock(&pHddCtx->roc_lock);
1560bypass_lock:
Rashmi Ramannac7744532013-10-06 16:49:08 +05301561 hddLog(VOS_TRACE_LEVEL_INFO,
1562 "action frame: Request ROC for wait time %u", wait);
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 INIT_COMPLETION(pAdapter->offchannel_tx_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001564 status = wlan_hdd_request_remain_on_channel(wiphy, dev,
Yue Maf49ba872013-08-19 12:04:25 -07001565 chan,
1566#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1567 channel_type,
1568#endif
1569 wait, cookie,
Agarwal Ashish7875e7c2014-03-11 12:54:57 +05301570 req_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07001571
1572 if(0 != status)
1573 {
1574 if( (-EBUSY == status) &&
1575 (cfgState->current_freq == chan->center_freq) )
1576 {
1577 goto send_frame;
1578 }
1579 goto err_rem_channel;
1580 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001581 /* Wait for driver to be ready on the requested channel */
1582 status = wait_for_completion_interruptible_timeout(
1583 &pAdapter->offchannel_tx_event,
1584 msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
c_hpothu7f63e882013-10-02 19:13:35 +05301585 if(0 >= status)
Jeff Johnson295189b2012-06-20 16:38:30 -07001586 {
c_hpothu7f63e882013-10-02 19:13:35 +05301587 hddLog( LOGE, "wait on offchannel_tx_event failed %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001588 goto err_rem_channel;
1589 }
1590 }
1591 else if ( offchan )
1592 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001593 /* Check before sending action frame
1594 whether we already remain on channel */
Jeff Johnson295189b2012-06-20 16:38:30 -07001595 if(NULL == cfgState->remain_on_chan_ctx)
1596 {
1597 goto err_rem_channel;
1598 }
1599 }
1600 send_frame:
1601#endif
1602
Jeff Johnsone7245742012-09-05 17:12:55 -07001603 if(!noack)
1604 {
1605 cfgState->buf = vos_mem_malloc( len ); //buf;
1606 if( cfgState->buf == NULL )
1607 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07001608
Jeff Johnsone7245742012-09-05 17:12:55 -07001609 cfgState->len = len;
Jeff Johnson295189b2012-06-20 16:38:30 -07001610
Jeff Johnsone7245742012-09-05 17:12:55 -07001611 vos_mem_copy( cfgState->buf, buf, len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001612
Ganesh Kondabattinicdacf812015-09-01 12:36:09 +05301613 mutex_lock(&pHddCtx->roc_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07001614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001615 if( cfgState->remain_on_chan_ctx )
1616 {
1617 cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
1618 *cookie = cfgState->action_cookie;
1619 }
1620 else
1621 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001622#endif
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001623 *cookie = (uintptr_t) cfgState->buf;
Jeff Johnsone7245742012-09-05 17:12:55 -07001624 cfgState->action_cookie = *cookie;
Jeff Johnson295189b2012-06-20 16:38:30 -07001625#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnsone7245742012-09-05 17:12:55 -07001626 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001627#endif
Ganesh Kondabattinicdacf812015-09-01 12:36:09 +05301628 mutex_unlock(&pHddCtx->roc_lock);
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301629 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001630
1631 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
Jeff Johnsone7245742012-09-05 17:12:55 -07001632 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
1633 ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07001634 )
1635 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001636 tANI_U8 sessionId = pAdapter->sessionId;
Hoonki Lee1090c6a2013-01-16 17:40:54 -08001637
Jeff Johnsone7245742012-09-05 17:12:55 -07001638 if ((type == SIR_MAC_MGMT_FRAME) &&
1639 (subType == SIR_MAC_MGMT_ACTION) &&
Rajeev Kumar Sirasanagandlaac6345d2017-08-30 23:09:08 +05301640 wlan_hdd_is_type_p2p_action(
1641 &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET],
1642 len - mgmt_hdr_len))
Jeff Johnson295189b2012-06-20 16:38:30 -07001643 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001644 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Rashmi Ramannac7744532013-10-06 16:49:08 +05301645 hddLog(LOG1, "Tx Action Frame %u.", actionFrmType);
Jeff Johnsone7245742012-09-05 17:12:55 -07001646 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
Jeff Johnson295189b2012-06-20 16:38:30 -07001647 {
Jeff Johnsone7245742012-09-05 17:12:55 -07001648 cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301649 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING.", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07001650 }
1651 else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
1652 {
1653 cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
Rashmi Ramannac7744532013-10-06 16:49:08 +05301654 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING.", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001655 }
1656 }
Abhishek Singh0ebac9c2014-06-25 13:34:12 +05301657
Jeff Johnson295189b2012-06-20 16:38:30 -07001658 if (eHAL_STATUS_SUCCESS !=
1659 sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
Kaushik, Sushant7005e372014-04-08 11:36:54 +05301660 sessionId, buf, len, wait, noack))
Jeff Johnson295189b2012-06-20 16:38:30 -07001661 {
1662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1663 "%s: sme_sendAction returned fail", __func__);
1664 goto err;
1665 }
1666 }
Deepthi Gowrie4c98032016-06-17 15:24:57 +05301667 else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
1668 ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
1669 )
Jeff Johnson295189b2012-06-20 16:38:30 -07001670 {
Jeff Johnson43971f52012-07-17 12:26:56 -07001671 if( VOS_STATUS_SUCCESS !=
Jeff Johnson295189b2012-06-20 16:38:30 -07001672 WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
Jeff Johnsone7245742012-09-05 17:12:55 -07001673 buf, len, 0 ) )
Jeff Johnson295189b2012-06-20 16:38:30 -07001674 {
1675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1676 "%s: WLANSAP_SendAction returned fail", __func__);
1677 goto err;
1678 }
1679 }
1680
1681 return 0;
1682err:
Jeff Johnsone7245742012-09-05 17:12:55 -07001683 if(!noack)
1684 {
1685 hdd_sendActionCnf( pAdapter, FALSE );
1686 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001687 return 0;
1688err_rem_channel:
Jeff Johnsonf67dca92013-11-08 17:07:40 -08001689 *cookie = (uintptr_t)cfgState;
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001690 cfg80211_mgmt_tx_status(
1691#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1692 pAdapter->dev->ieee80211_ptr,
1693#else
1694 pAdapter->dev,
1695#endif
1696 *cookie, buf, len, FALSE, GFP_KERNEL );
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05301697 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07001698 return 0;
1699}
1700
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05301701#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
1702int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
1703 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
1704#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301705int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct wireless_dev *wdev,
1706 struct ieee80211_channel *chan, bool offchan,
1707#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1708 enum nl80211_channel_type channel_type,
1709 bool channel_type_valid,
1710#endif
1711 unsigned int wait,
1712 const u8 *buf, size_t len, bool no_cck,
1713 bool dont_wait_for_ack, u64 *cookie )
1714#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1715int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1716 struct ieee80211_channel *chan, bool offchan,
1717 enum nl80211_channel_type channel_type,
1718 bool channel_type_valid, unsigned int wait,
1719 const u8 *buf, size_t len, bool no_cck,
1720 bool dont_wait_for_ack, u64 *cookie )
1721#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1722int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1723 struct ieee80211_channel *chan, bool offchan,
1724 enum nl80211_channel_type channel_type,
1725 bool channel_type_valid, unsigned int wait,
1726 const u8 *buf, size_t len, u64 *cookie )
1727#else
1728int wlan_hdd_mgmt_tx( struct wiphy *wiphy, struct net_device *dev,
1729 struct ieee80211_channel *chan,
1730 enum nl80211_channel_type channel_type,
1731 bool channel_type_valid,
1732 const u8 *buf, size_t len, u64 *cookie )
1733#endif //LINUX_VERSION_CODE
1734{
1735 int ret;
1736
1737 vos_ssr_protect(__func__);
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05301738#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0))
1739 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan,
1740 params->wait, params->buf, params->len,
1741 params->no_cck, params->dont_wait_for_ack,
1742 cookie);
1743#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301744 ret = __wlan_hdd_mgmt_tx(wiphy, wdev,
1745 chan, offchan,
1746#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
1747 channel_type,
1748 channel_type_valid,
1749#endif
1750 wait,
1751 buf, len, no_cck,
1752 dont_wait_for_ack, cookie);
1753#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
1754 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1755 channel_type, channel_type_valid, wait,
1756 buf, len, no_cck,
1757 dont_wait_for_ack, cookie);
1758#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1759 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, offchan,
1760 channel_type, channel_type_valid, wait,
1761 buf, len, cookie);
1762#else
1763 ret = __wlan_hdd_mgmt_tx(wiphy, dev, chan, channel_type,
1764 channel_type_valid, buf, len, cookie);
1765#endif //LINUX_VERSION_CODE
1766 vos_ssr_unprotect(__func__);
1767
1768 return ret;
1769}
1770
Jeff Johnson295189b2012-06-20 16:38:30 -07001771#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001772#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301773int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001774 struct wireless_dev *wdev,
1775 u64 cookie)
1776{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301777 u64 cookie_dummy;
1778 cookie_dummy = cookie << 32;
1779 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1780 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT, NO_SESSION, cookie_dummy));
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001781 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, wdev, cookie );
1782}
1783#else
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301784int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
Jeff Johnson295189b2012-06-20 16:38:30 -07001785 struct net_device *dev,
1786 u64 cookie)
1787{
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05301788 u64 cookie_dummy;
1789 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
1790 cookie_dummy = cookie << 32;
1791 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
1792 TRACE_CODE_HDD_MGMT_TX_CANCEL_WAIT,
1793 pAdapter->sessionId, cookie_dummy));
Jeff Johnson295189b2012-06-20 16:38:30 -07001794 return wlan_hdd_cfg80211_cancel_remain_on_channel( wiphy, dev, cookie );
1795}
1796#endif
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001797#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001798
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05301799#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1800#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1801int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1802 struct wireless_dev *wdev,
1803 u64 cookie)
1804{
1805 int ret;
1806
1807 vos_ssr_protect(__func__);
1808 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1809 vos_ssr_unprotect(__func__);
1810
1811 return ret;
1812}
1813#else
1814int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1815 struct net_device *dev,
1816 u64 cookie)
1817{
1818 int ret;
1819
1820 vos_ssr_protect(__func__);
1821 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, dev, cookie);
1822 vos_ssr_unprotect(__func__);
1823
1824 return ret;
1825}
1826#endif
1827#endif
1828
Jeff Johnson295189b2012-06-20 16:38:30 -07001829void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess )
1830{
1831 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1832
Jeff Johnsone7245742012-09-05 17:12:55 -07001833 cfgState->actionFrmState = HDD_IDLE;
1834
Jeff Johnson295189b2012-06-20 16:38:30 -07001835 if( NULL == cfgState->buf )
1836 {
Jeff Johnson295189b2012-06-20 16:38:30 -07001837 return;
1838 }
Deepthi Gowri108809c2016-06-16 18:04:24 +05301839 if (cfgState->is_go_neg_ack_received)
1840 {
1841 cfgState->is_go_neg_ack_received = 0;
1842 /* Sometimes its possible that host may receive the ack for GO
1843 * negotiation req after sending go negotaition confirmation,
1844 * in such case drop the ack received for the go negotiation
1845 * request, so that supplicant waits for the confirmation ack
1846 * from firmware.
1847 */
1848 hddLog( LOG1, FL("Drop the pending ack received in cfgState->actionFrmState %d"),
1849 cfgState->actionFrmState);
1850 return;
1851 }
1852
1853 hddLog( LOG1, "Send Action cnf, actionSendSuccess %d", actionSendSuccess);
Jeff Johnson295189b2012-06-20 16:38:30 -07001854
1855 /* If skb is NULL it means this packet was received on CFG80211 interface
1856 * else it was received on Monitor interface */
1857 if( cfgState->skb == NULL )
1858 {
1859 /*
1860 * buf is the same pointer it passed us to send. Since we are sending
1861 * it through control path, we use different buffers.
1862 * In case of mac80211, they just push it to the skb and pass the same
1863 * data while sending tx ack status.
1864 * */
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08001865 cfg80211_mgmt_tx_status(
1866#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
1867 pAdapter->dev->ieee80211_ptr,
1868#else
1869 pAdapter->dev,
1870#endif
1871 cfgState->action_cookie,
Jeff Johnson295189b2012-06-20 16:38:30 -07001872 cfgState->buf, cfgState->len, actionSendSuccess, GFP_KERNEL );
1873 vos_mem_free( cfgState->buf );
1874 cfgState->buf = NULL;
1875 }
1876 else
1877 {
1878 hdd_adapter_t* pMonAdapter =
1879 hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_MONITOR );
1880 if( pMonAdapter == NULL )
1881 {
1882 hddLog( LOGE, "Not able to get Monitor Adapter");
1883 cfgState->skb = NULL;
1884 vos_mem_free( cfgState->buf );
1885 cfgState->buf = NULL;
1886 complete(&pAdapter->tx_action_cnf_event);
1887 return;
1888 }
1889 /* Send TX completion feedback over monitor interface. */
1890 hdd_wlan_tx_complete( pMonAdapter, cfgState, actionSendSuccess );
1891 cfgState->skb = NULL;
1892 vos_mem_free( cfgState->buf );
1893 cfgState->buf = NULL;
1894 /* Look for the next Mgmt packet to TX */
1895 hdd_mon_tx_mgmt_pkt(pAdapter);
1896 }
1897 complete(&pAdapter->tx_action_cnf_event);
1898}
1899
1900/**
1901 * hdd_setP2pNoa
1902 *
1903 *FUNCTION:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301904 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson295189b2012-06-20 16:38:30 -07001905 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1906 *
1907 *LOGIC:
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301908 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
Jeff Johnson295189b2012-06-20 16:38:30 -07001909 *
1910 *ASSUMPTIONS:
1911 *
1912 *
1913 *NOTE:
1914 *
1915 * @param dev Pointer to net device structure
Daram Sudha1f7e0e92013-12-17 07:52:31 +05301916 * @param command Pointer to command
Jeff Johnson295189b2012-06-20 16:38:30 -07001917 *
1918 * @return Status
1919 */
1920
1921int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
1922{
1923 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1924 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1925 VOS_STATUS status = VOS_STATUS_SUCCESS;
1926 tP2pPsConfig NoA;
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001927 int count, duration, start_time;
Jeff Johnson295189b2012-06-20 16:38:30 -07001928 char *param;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001929 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001930
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001931 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07001932 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05301933 {
1934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1935 "%s: strnchr failed to find delimeter",__func__);
1936 return -EINVAL;
1937 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001938 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08001939 ret = sscanf(param, "%d %d %d", &count, &start_time, &duration);
1940 if (ret < 3)
1941 {
1942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1943 "%s: P2P_SET GO NoA: fail to read param "
Sushant Kaushik87787972015-09-11 16:05:00 +05301944 "count=%d duration=%d interval=%d ",
kalikinkar dhara19d77182013-11-12 14:29:46 -08001945 __func__, count, start_time, duration);
1946 return -EINVAL;
1947 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001949 "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d",
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001950 __func__, count, start_time, duration);
1951 duration = MS_TO_MUS(duration);
Jeff Johnson295189b2012-06-20 16:38:30 -07001952 /* PS Selection
1953 * Periodic NoA (2)
1954 * Single NOA (4)
1955 */
1956 NoA.opp_ps = 0;
1957 NoA.ctWindow = 0;
1958 if (count == 1)
1959 {
1960 NoA.duration = 0;
1961 NoA.single_noa_duration = duration;
1962 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1963 }
1964 else
1965 {
1966 NoA.duration = duration;
1967 NoA.single_noa_duration = 0;
1968 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1969 }
Madan Mohan Koyyalamudi4b63eee2012-11-06 18:47:56 -08001970 NoA.interval = MS_TO_MUS(100);
Jeff Johnson295189b2012-06-20 16:38:30 -07001971 NoA.count = count;
1972 NoA.sessionid = pAdapter->sessionId;
1973
1974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1975 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1976 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08001977 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07001978 NoA.ctWindow, NoA.duration, NoA.interval,
1979 NoA.count, NoA.single_noa_duration,
1980 NoA.psSelection);
1981
1982 sme_p2pSetPs(hHal, &NoA);
1983 return status;
1984}
1985
1986/**
1987 * hdd_setP2pOpps
1988 *
1989 *FUNCTION:
1990 * This function is called from hdd_hostapd_ioctl function when Driver
1991 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1992 *
1993 *LOGIC:
1994 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1995 *
1996 *ASSUMPTIONS:
1997 *
1998 *
1999 *NOTE:
2000 *
2001 * @param dev Pointer to net device structure
2002 * @param command Pointer to command
2003 *
2004 * @return Status
2005 */
2006
2007int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
2008{
2009 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2010 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
2011 VOS_STATUS status = VOS_STATUS_SUCCESS;
2012 tP2pPsConfig NoA;
2013 char *param;
2014 int legacy_ps, opp_ps, ctwindow;
kalikinkar dhara19d77182013-11-12 14:29:46 -08002015 tANI_U8 ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002016
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08002017 param = strnchr(command, strlen(command), ' ');
Jeff Johnson295189b2012-06-20 16:38:30 -07002018 if (param == NULL)
c_hpothu7f63e882013-10-02 19:13:35 +05302019 {
2020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2021 "%s: strnchr failed to find delimeter",__func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08002022 return -EINVAL;
c_hpothu7f63e882013-10-02 19:13:35 +05302023 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002024 param++;
kalikinkar dhara19d77182013-11-12 14:29:46 -08002025 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
2026 if (ret < 3)
2027 {
2028 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2029 "%s: P2P_SET GO PS: fail to read param "
Sushant Kaushik87787972015-09-11 16:05:00 +05302030 " legacy_ps=%d opp_ps=%d ctwindow=%d ",
kalikinkar dhara19d77182013-11-12 14:29:46 -08002031 __func__, legacy_ps, opp_ps, ctwindow);
2032 return -EINVAL;
2033 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002034 VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002035 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Jeff Johnson295189b2012-06-20 16:38:30 -07002036 __func__, legacy_ps, opp_ps, ctwindow);
2037
2038 /* PS Selection
2039 * Opportunistic Power Save (1)
2040 */
2041
2042 /* From wpa_cli user need to use separate command to set ctWindow and Opps
2043 * When user want to set ctWindow during that time other parameters
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302044 * values are coming from wpa_supplicant as -1.
2045 * Example : User want to set ctWindow with 30 then wpa_cli command :
2046 * P2P_SET ctwindow 30
2047 * Command Received at hdd_hostapd_ioctl is as below:
Jeff Johnson295189b2012-06-20 16:38:30 -07002048 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302049 */
Jeff Johnson295189b2012-06-20 16:38:30 -07002050 if (ctwindow != -1)
2051 {
2052
2053 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002054 "Opportunistic Power Save is %s",
Jeff Johnson295189b2012-06-20 16:38:30 -07002055 (TRUE == pAdapter->ops) ? "Enable" : "Disable" );
2056
2057 if (ctwindow != pAdapter->ctw)
2058 {
2059 pAdapter->ctw = ctwindow;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302060
Jeff Johnson295189b2012-06-20 16:38:30 -07002061 if(pAdapter->ops)
2062 {
2063 NoA.opp_ps = pAdapter->ops;
2064 NoA.ctWindow = pAdapter->ctw;
2065 NoA.duration = 0;
2066 NoA.single_noa_duration = 0;
2067 NoA.interval = 0;
2068 NoA.count = 0;
2069 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
2070 NoA.sessionid = pAdapter->sessionId;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302071
Jeff Johnson295189b2012-06-20 16:38:30 -07002072 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2073 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
2074 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002075 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07002076 NoA.ctWindow, NoA.duration, NoA.interval,
2077 NoA.count, NoA.single_noa_duration,
2078 NoA.psSelection);
2079
2080 sme_p2pSetPs(hHal, &NoA);
2081 }
2082 return 0;
2083 }
2084 }
2085
2086 if (opp_ps != -1)
2087 {
2088 pAdapter->ops = opp_ps;
2089
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302090 if ((opp_ps != -1) && (pAdapter->ctw))
Jeff Johnson295189b2012-06-20 16:38:30 -07002091 {
2092 NoA.opp_ps = opp_ps;
2093 NoA.ctWindow = pAdapter->ctw;
2094 NoA.duration = 0;
2095 NoA.single_noa_duration = 0;
2096 NoA.interval = 0;
2097 NoA.count = 0;
2098 NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
2099 NoA.sessionid = pAdapter->sessionId;
2100
2101 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2102 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
2103 "interval %d count %d single noa duration %d "
Arif Hussain6d2a3322013-11-17 19:50:10 -08002104 "PsSelection %x", __func__, NoA.opp_ps,
Jeff Johnson295189b2012-06-20 16:38:30 -07002105 NoA.ctWindow, NoA.duration, NoA.interval,
2106 NoA.count, NoA.single_noa_duration,
2107 NoA.psSelection);
2108
2109 sme_p2pSetPs(hHal, &NoA);
2110 }
2111 }
2112 return status;
2113}
2114
2115int hdd_setP2pPs( struct net_device *dev, void *msgData )
2116{
2117 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2118 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
2119 VOS_STATUS status = VOS_STATUS_SUCCESS;
2120 tP2pPsConfig NoA;
2121 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
2122
2123 NoA.opp_ps = pappNoA->opp_ps;
2124 NoA.ctWindow = pappNoA->ctWindow;
2125 NoA.duration = pappNoA->duration;
2126 NoA.interval = pappNoA->interval;
2127 NoA.count = pappNoA->count;
2128 NoA.single_noa_duration = pappNoA->single_noa_duration;
2129 NoA.psSelection = pappNoA->psSelection;
2130 NoA.sessionid = pAdapter->sessionId;
2131
2132 sme_p2pSetPs(hHal, &NoA);
2133 return status;
2134}
Jeff Johnson295189b2012-06-20 16:38:30 -07002135
2136static tANI_U8 wlan_hdd_get_session_type( enum nl80211_iftype type )
2137{
2138 tANI_U8 sessionType;
2139
2140 switch( type )
2141 {
2142 case NL80211_IFTYPE_AP:
2143 sessionType = WLAN_HDD_SOFTAP;
2144 break;
2145 case NL80211_IFTYPE_P2P_GO:
2146 sessionType = WLAN_HDD_P2P_GO;
2147 break;
2148 case NL80211_IFTYPE_P2P_CLIENT:
2149 sessionType = WLAN_HDD_P2P_CLIENT;
2150 break;
2151 case NL80211_IFTYPE_STATION:
2152 sessionType = WLAN_HDD_INFRA_STATION;
2153 break;
2154 case NL80211_IFTYPE_MONITOR:
2155 sessionType = WLAN_HDD_MONITOR;
2156 break;
2157 default:
2158 sessionType = WLAN_HDD_INFRA_STATION;
2159 break;
2160 }
2161
2162 return sessionType;
2163}
2164
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302165/**
2166 * hdd_close_all_adapters_per_mode() - close all adapters per mode
2167 * @hdd_ctx: pointer to hdd context
2168 * @mode: all adapters to be deleted in this mode
2169 *
2170 * Return: None
2171 */
2172static void
2173hdd_close_all_adapters_per_mode(hdd_context_t *hdd_ctx,
2174 uint32_t mode)
2175{
2176 hdd_adapter_t *adapter = hdd_get_adapter(hdd_ctx, mode);
2177
2178 while (adapter) {
2179 hdd_stop_adapter(hdd_ctx, adapter, VOS_TRUE);
2180 hdd_deinit_adapter(hdd_ctx, adapter, TRUE);
2181 hdd_close_adapter(hdd_ctx, adapter, VOS_TRUE);
2182
2183 adapter = hdd_get_adapter(hdd_ctx, mode);
2184 }
2185}
2186
2187static void wlan_hdd_create_p2p_adapter(hdd_context_t *hdd_ctx,
2188 tANI_U8 rtnl_held)
2189{
2190 hdd_adapter_t *p2p_adapter;
2191
2192 p2p_adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_P2P_DEVICE, "p2p%d",
2193 &hdd_ctx->p2pDeviceAddress.bytes[0],
2194 rtnl_held);
2195 if (!p2p_adapter)
2196 hddLog(LOGE,
2197 FL("Failed to do hdd_open_adapter for P2P Device Interface"));
2198}
2199
2200/**
2201 * wlan_hdd_add_monitor_check() - check for monitor intf and add if needed
2202 * @hdd_ctx: pointer to hdd context
2203 * @adapter: output pointer to hold created monitor adapter
2204 * @type: type of the interface
2205 * @name: name of the interface
2206 *
2207 * Return: 0 - on success
2208 * 1 - on failure
2209 */
2210static int
2211wlan_hdd_add_monitor_check(hdd_context_t *hdd_ctx, hdd_adapter_t **adapter,
2212 enum nl80211_iftype type, const char *name)
2213{
2214 hdd_adapter_t *sta_adapter;
2215 hdd_adapter_t *mon_adapter;
2216 uint32_t i;
2217
2218 *adapter = NULL;
2219
2220 /*
2221 * If add interface request is for monitor mode, then it can run in
2222 * parallel with only one station interface.
2223 * If there is no existing station interface return error
2224 */
2225 if (type != NL80211_IFTYPE_MONITOR)
2226 return 0;
2227
2228 if (!sme_IsFeatureSupportedByFW(STA_MONITOR_SCC)) {
2229 hddLog(LOGE, FL("No FW support for STA + MON SCC"));
2230 return -EINVAL;
2231 }
2232
2233 if (hdd_ctx->no_of_open_sessions[VOS_MONITOR_MODE]) {
2234 hddLog(VOS_TRACE_LEVEL_ERROR,
2235 "%s: monitor mode already exists, only one is possible",
2236 __func__);
2237
2238 return -EBUSY;
2239 }
2240
2241 /* Ensure there is only one station interface */
2242 if (hdd_ctx->no_of_open_sessions[VOS_STA_MODE] != 1) {
2243 hddLog(LOGE,
2244 FL("cannot add monitor mode, due to %u sta interfaces"),
2245 hdd_ctx->no_of_open_sessions[VOS_STA_MODE]);
2246
2247 return -EINVAL;
2248 }
2249
2250 sta_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_INFRA_STATION);
2251 if (!sta_adapter) {
2252 hddLog(LOGE, FL("No station adapter"));
2253 return -EINVAL;
2254 }
2255
2256 /* delete all the other interfaces */
2257 for (i = VOS_STA_SAP_MODE; i <= VOS_P2P_DEVICE; i++) {
2258 if (i == VOS_FTM_MODE || i == VOS_MONITOR_MODE)
2259 continue;
2260
2261 hdd_close_all_adapters_per_mode(hdd_ctx, i);
2262 }
2263
2264 mon_adapter = hdd_open_adapter(hdd_ctx, WLAN_HDD_MONITOR, name,
2265 wlan_hdd_get_intf_addr(hdd_ctx),
2266 VOS_TRUE);
2267 if (!mon_adapter) {
2268 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",
2269 __func__);
2270 wlan_hdd_create_p2p_adapter(hdd_ctx, TRUE);
2271 return -EINVAL;
2272 }
2273
2274 *adapter = mon_adapter;
2275 return 0;
2276}
2277
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302278#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2279static struct wireless_dev *
2280__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2281 const char *name,
2282 unsigned char name_assign_type,
2283 enum nl80211_iftype type,
2284 u32 *flags,
2285 struct vif_params *params)
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002286#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302287static struct net_device *
2288__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2289 const char *name,
2290 unsigned char name_assign_type,
2291 enum nl80211_iftype type,
2292 u32 *flags,
2293 struct vif_params *params)
Jeff Johnson295189b2012-06-20 16:38:30 -07002294#else
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302295static int
2296__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2297 const char *name,
2298 unsigned char name_assign_type,
2299 enum nl80211_iftype type,
2300 u32 *flags,
2301 struct vif_params *params)
Jeff Johnson295189b2012-06-20 16:38:30 -07002302#endif
2303{
2304 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302305 hdd_adapter_t *pAdapter = NULL;
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05302306 hdd_scaninfo_t *pScanInfo = NULL;
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302307 int ret = 0;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302308
Jeff Johnson295189b2012-06-20 16:38:30 -07002309 ENTER();
2310
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302311 ret = wlan_hdd_validate_context(pHddCtx);
2312 if (0 != ret)
2313 {
Masti, Narayanraddic80e2bf2015-01-27 16:39:00 +05302314#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2315 return ERR_PTR(-EINVAL);
2316#else
2317 return -EAGAIN;
2318#endif
2319 }
2320
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302321 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2322 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
Agarwal Ashish4cfa1e52014-05-09 20:25:11 +05302323 if (WLAN_HDD_P2P_CLIENT != wlan_hdd_get_session_type(type) &&
2324 WLAN_HDD_INFRA_STATION != wlan_hdd_get_session_type(type) &&
2325 hdd_get_adapter(pHddCtx, wlan_hdd_get_session_type(type)) != NULL)
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002326 {
Jeff Johnsond13512a2012-07-17 11:42:19 -07002327 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Interface type %d already exists. Two"
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002328 "interfaces of same type are not supported currently.",__func__, type);
c_hpothu471fc962014-06-24 16:06:53 +05302329#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2330 return ERR_PTR(-EINVAL);
2331#else
2332 return -EAGAIN;
2333#endif
Jeff Johnson04dd8a82012-06-29 20:41:40 -07002334 }
2335
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302336 if (pHddCtx->concurrency_mode == VOS_STA_MON) {
2337 hddLog(VOS_TRACE_LEVEL_ERROR,
2338 "%s: STA + MONITOR mode is in progress, cannot add new interface",
2339 __func__);
2340#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2341 return ERR_PTR(-EINVAL);
2342#else
2343 return -EBUSY;
2344#endif
2345 }
2346
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05302347 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2348 pScanInfo = &pHddCtx->scan_info;
2349 if ((pScanInfo != NULL) && (pAdapter != NULL) &&
2350 (pHddCtx->scan_info.mScanPending))
2351 {
2352 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
2353 eCSR_SCAN_ABORT_DEFAULT);
2354 hddLog(VOS_TRACE_LEVEL_INFO,
2355 "%s: Abort Scan while adding virtual interface",__func__);
2356 }
2357
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302358 ret = wlan_hdd_add_monitor_check(pHddCtx, &pAdapter, type, name);
2359 if (ret) {
2360#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2361 return ERR_PTR(-EINVAL);
2362#else
2363 return ret;
2364#endif
2365 }
2366
2367 if (pAdapter)
2368 goto return_adapter;
2369
Rashmi Ramanna8f122ce2014-05-28 22:42:12 +05302370 pAdapter = NULL;
Kiet Lam04e26912013-10-18 20:13:38 +05302371 if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated &&
2372 ((NL80211_IFTYPE_P2P_GO == type) ||
2373 (NL80211_IFTYPE_P2P_CLIENT == type)))
Jeff Johnson295189b2012-06-20 16:38:30 -07002374 {
Jeff Johnson295189b2012-06-20 16:38:30 -07002375 /* Generate the P2P Interface Address. this address must be
2376 * different from the P2P Device Address.
2377 */
2378 v_MACADDR_t p2pDeviceAddress = pHddCtx->p2pDeviceAddress;
2379 p2pDeviceAddress.bytes[4] ^= 0x80;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302380 pAdapter = hdd_open_adapter( pHddCtx,
Jeff Johnson295189b2012-06-20 16:38:30 -07002381 wlan_hdd_get_session_type(type),
2382 name, p2pDeviceAddress.bytes,
2383 VOS_TRUE );
Jeff Johnson295189b2012-06-20 16:38:30 -07002384 }
2385 else
2386 {
2387 pAdapter = hdd_open_adapter( pHddCtx, wlan_hdd_get_session_type(type),
2388 name, wlan_hdd_get_intf_addr(pHddCtx), VOS_TRUE );
2389 }
2390
2391 if( NULL == pAdapter)
2392 {
2393 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
2394#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
c_hpothu471fc962014-06-24 16:06:53 +05302395 return ERR_PTR(-EINVAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07002396#else
2397 return -EINVAL;
2398#endif
2399 }
Masti, Narayanraddi41d82f02015-06-12 14:04:11 +05302400
Bala Venkatesh5c06a252018-07-12 16:08:04 +05302401 if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO ||
2402 type == NL80211_IFTYPE_AP)
Masti, Narayanraddi575ccc72015-08-17 18:04:57 +05302403 {
2404 /* Below function Notifies Mode change and
2405 * If p2p session is detected then invokes functionality to
2406 * Teardown TDLS links and disable offchannel if any. Since
2407 * TDLS is not supported in case of concurrency.
2408 */
2409 hddLog(LOG1, FL("Interface type = %d"), type);
2410 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
2411 }
Masti, Narayanraddi41d82f02015-06-12 14:04:11 +05302412
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302413return_adapter:
2414
Jeff Johnson295189b2012-06-20 16:38:30 -07002415 EXIT();
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002416#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2417 return pAdapter->dev->ieee80211_ptr;
2418#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
Jeff Johnson295189b2012-06-20 16:38:30 -07002419 return pAdapter->dev;
2420#else
2421 return 0;
2422#endif
2423}
2424
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302425#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2426struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2427 const char *name,
2428 unsigned char name_assign_type,
2429 enum nl80211_iftype type,
2430 struct vif_params *params)
2431{
2432 struct wireless_dev *wdev;
2433
2434 vos_ssr_protect(__func__);
2435 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
2436 type, &params->flags, params);
2437 vos_ssr_unprotect(__func__);
2438
2439 return wdev;
2440}
2441#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || \
2442 defined(WITH_BACKPORTS)
2443/**
2444 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
2445 * @wiphy: wiphy pointer
2446 * @name: User-visible name of the interface
2447 * @name_assign_type: the name of assign type of the netdev
2448 * @nl80211_iftype: (virtual) interface types
2449 * @flags: monitor mode configuration flags (not used)
2450 * @vif_params: virtual interface parameters (not used)
2451 *
2452 * Return: the pointer of wireless dev, otherwise ERR_PTR.
2453 */
2454struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2455 const char *name,
2456 unsigned char name_assign_type,
2457 enum nl80211_iftype type,
2458 u32 *flags,
2459 struct vif_params *params)
2460{
2461 struct wireless_dev *wdev;
2462
2463 vos_ssr_protect(__func__);
2464 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
2465 type, flags, params);
2466 vos_ssr_unprotect(__func__);
2467 return wdev;
2468
2469}
2470#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0))
2471/**
2472 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
2473 * @wiphy: wiphy pointer
2474 * @name: User-visible name of the interface
2475 * @nl80211_iftype: (virtual) interface types
2476 * @flags: monitor mode configuration flags (not used)
2477 * @vif_params: virtual interface parameters (not used)
2478 *
2479 * Return: the pointer of wireless dev, otherwise ERR_PTR.
2480 */
2481struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2482 const char *name,
2483 enum nl80211_iftype type,
2484 u32 *flags,
2485 struct vif_params *params)
2486{
2487 struct wireless_dev *wdev;
2488 unsigned char name_assign_type = 0;
2489
2490 vos_ssr_protect(__func__);
2491 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
2492 type, flags, params);
2493 vos_ssr_unprotect(__func__);
2494 return wdev;
2495
2496}
2497
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302498#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2499struct wireless_dev* wlan_hdd_add_virtual_intf(
2500 struct wiphy *wiphy, char *name, enum nl80211_iftype type,
2501 u32 *flags, struct vif_params *params )
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302502{
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302503 struct wireless_dev *wdev;
2504 unsigned char name_assign_type = 0;
2505
2506 vos_ssr_protect(__func__);
2507 wdev = __wlan_hdd_add_virtual_intf(wiphy, (const char *)name,
2508 name_assign_type,
2509 type, flags, params);
2510 vos_ssr_unprotect(__func__);
2511 return wdev;
2512
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302513}
2514
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302515#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
2516struct net_device* wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2517 char *name,
2518 enum nl80211_iftype type,
2519 u32 *flags,
2520 struct vif_params *params)
2521{
2522 struct net_device *ndev;
2523 unsigned char name_assign_type = 0;
2524
2525 vos_ssr_protect(__func__);
2526 ndev = __wlan_hdd_add_virtual_intf(wiphy, (const char *)name, name_assign_type,
2527 type, flags, params);
2528 vos_ssr_unprotect(__func__);
2529 return wdev;
2530
2531}
2532#else
2533int wlan_hdd_add_virtual_intf(struct wiphy *wiphy, char *name,
2534 enum nl80211_iftype type,
2535 u32 *flags, struct vif_params *params)
2536{
2537 int ret;
2538 unsigned char name_assign_type = 0;
2539
2540 vos_ssr_protect(__func__);
2541 ret = __wlan_hdd_add_virtual_intf(wiphy, (const char *)name, name_assign_type,
2542 type, flags, params);
2543 vos_ssr_unprotect(__func__);
2544
2545 return ret;
2546}
2547#endif
2548
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302549/**
2550 * hdd_delete_adapter() - stop and close adapter
2551 * @hdd_ctx: pointer to hdd context
2552 * @adapter: adapter to be deleted
2553 * @rtnl_held: rtnl lock held
2554 *
2555 * Rerurn: None
2556 */
2557static void
2558hdd_delete_adapter(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2559 tANI_U8 rtnl_held)
2560{
2561 wlan_hdd_release_intf_addr(hdd_ctx, adapter->macAddressCurrent.bytes);
2562 hdd_stop_adapter(hdd_ctx, adapter, VOS_TRUE);
Sourav Mohapatra47b07a02019-08-22 10:23:18 +05302563 hdd_deinit_adapter(hdd_ctx, adapter, TRUE);
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302564 hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
2565}
2566
2567/**
2568 * wlan_hdd_del_monitor() - delete monitor interface
2569 * @hdd_ctx: pointer to hdd context
2570 * @adapter: adapter to be deleted
2571 * @rtnl_held: rtnl lock held
2572 *
2573 * This function is invoked to delete monitor interface and also
2574 * station interface if needed.
2575 *
2576 * Return: None
2577 */
2578static void
2579wlan_hdd_del_monitor(hdd_context_t *hdd_ctx, hdd_adapter_t *adapter,
2580 tANI_U8 rtnl_held)
2581{
2582 hdd_adapter_t *monitor_adapter;
2583 bool delete_station = false;
2584
2585 monitor_adapter = hdd_get_adapter(hdd_ctx, WLAN_HDD_MONITOR);
2586 if (monitor_adapter != adapter)
2587 delete_station = true;
2588
2589 /* delete the monitor adapter and re-create the p2p-dev adapter */
2590 hdd_delete_adapter(hdd_ctx, monitor_adapter, rtnl_held);
2591
2592 wlan_hdd_create_p2p_adapter(hdd_ctx, rtnl_held);
2593
2594 if (delete_station)
2595 hdd_delete_adapter(hdd_ctx, adapter, rtnl_held);
2596}
2597
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302598#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2599int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
2600#else
2601int __wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002602#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002603{
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08002604#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2605 struct net_device *dev = wdev->netdev;
2606#endif
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302607 hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy);
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302608 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302609 int status;
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +05302610
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302611 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07002612
Sushant Kaushik4b7cb302014-01-06 17:45:01 +05302613 MTRACE(vos_trace(VOS_MODULE_ID_HDD,
2614 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
2615 pAdapter->sessionId, pAdapter->device_mode));
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302616 hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302617 __func__,pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07002618
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302619 status = wlan_hdd_validate_context(pHddCtx);
2620
2621 if (0 != status)
2622 {
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302623 return status;
2624 }
2625
Rajeev Kumar Sirasanagandla8f11d542017-11-14 17:56:55 +05302626 if (pHddCtx->concurrency_mode == VOS_STA_MON)
2627 wlan_hdd_del_monitor(pHddCtx, pAdapter, TRUE);
2628 else
2629 hdd_delete_adapter(pHddCtx, pAdapter, TRUE);
Jeff Johnson295189b2012-06-20 16:38:30 -07002630
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +05302631 EXIT();
2632 return 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07002633}
2634
Mahesh A Saptasagar65570ad2014-06-23 21:05:38 +05302635#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2636int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct wireless_dev *wdev )
2637#else
2638int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev )
2639#endif
2640{
2641 int ret;
2642
2643 vos_ssr_protect(__func__);
2644#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2645 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
2646#else
2647 ret = __wlan_hdd_del_virtual_intf(wiphy, dev);
2648#endif
2649 vos_ssr_unprotect(__func__);
2650
2651 return ret;
2652}
2653
Jeff Johnson295189b2012-06-20 16:38:30 -07002654void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter,
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002655 tANI_U32 nFrameLength,
2656 tANI_U8* pbFrames,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302657 tANI_U8 frameType )
Jeff Johnson295189b2012-06-20 16:38:30 -07002658{
2659 //Indicate a Frame over Monitor Intf.
2660 int rxstat;
2661 struct sk_buff *skb = NULL;
2662 int needed_headroom = 0;
2663 int flag = HDD_RX_FLAG_IV_STRIPPED | HDD_RX_FLAG_DECRYPTED |
2664 HDD_RX_FLAG_MMIC_STRIPPED;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002665#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002666#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2667 hdd_context_t* pHddCtx = (hdd_context_t*)(pMonAdapter->pHddCtx);
2668#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002669#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002670 hddLog( LOG1, FL("Indicate Frame over Monitor Intf"));
2671
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002672 if (NULL == pbFrames)
2673 {
2674 hddLog(LOGE, FL("NULL frame pointer"));
2675 return;
2676 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002677
2678 /* room for the radiotap header based on driver features
2679 * 1 Byte for RADIO TAP Flag, 1 Byte padding and 2 Byte for
2680 * RX flags.
2681 * */
2682 needed_headroom = sizeof(struct ieee80211_radiotap_header) + 4;
2683
2684 //alloc skb here
2685 skb = alloc_skb(VPKT_SIZE_BUFFER, GFP_ATOMIC);
2686 if (unlikely(NULL == skb))
2687 {
2688 hddLog( LOGW, FL("Unable to allocate skb"));
2689 return;
2690 }
2691 skb_reserve(skb, VPKT_SIZE_BUFFER);
2692 if (unlikely(skb_headroom(skb) < nFrameLength))
2693 {
2694 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2695 "HDD [%d]: Insufficient headroom, "
Jeff Johnsonc135a9a2017-09-19 08:37:24 -07002696 "head[%pK], data[%pK], req[%d]",
Jeff Johnson295189b2012-06-20 16:38:30 -07002697 __LINE__, skb->head, skb->data, nFrameLength);
2698 kfree_skb(skb);
2699 return ;
2700 }
2701 // actually push the data
2702 memcpy(skb_push(skb, nFrameLength), pbFrames, nFrameLength);
2703 /* prepend radiotap information */
2704 if( 0 != hdd_wlan_add_rx_radiotap_hdr( skb, needed_headroom, flag ) )
2705 {
2706 hddLog( LOGE, FL("Not Able Add Radio Tap"));
2707 //free skb
2708 kfree_skb(skb);
2709 return ;
2710 }
2711
2712 skb_reset_mac_header( skb );
2713 skb->dev = pMonAdapter->dev;
2714 skb->protocol = eth_type_trans( skb, skb->dev );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07002715 skb->ip_summed = CHECKSUM_NONE;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002716#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07002717#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05302718 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
2719 HDD_WAKE_LOCK_DURATION,
2720 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Jeff Johnsone7245742012-09-05 17:12:55 -07002721#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08002722#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07002723 rxstat = netif_rx_ni(skb);
2724 if( NET_RX_SUCCESS == rxstat )
2725 {
2726 hddLog( LOG1, FL("Success"));
2727 }
2728 else
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302729 hddLog( LOGE, FL("Failed %d"), rxstat);
Jeff Johnson295189b2012-06-20 16:38:30 -07002730
2731 return ;
2732}
2733
Abhishek Singh7d624e12015-11-30 14:29:27 +05302734void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter,
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302735 tANI_U32 nFrameLength,
Jeff Johnson295189b2012-06-20 16:38:30 -07002736 tANI_U8* pbFrames,
2737 tANI_U8 frameType,
Chilam NG571c65a2013-01-19 12:27:36 +05302738 tANI_U32 rxChan,
Abhishek Singh7d624e12015-11-30 14:29:27 +05302739 tANI_S8 rxRssi)
Jeff Johnson295189b2012-06-20 16:38:30 -07002740{
2741 tANI_U16 freq;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302742 tANI_U16 extend_time;
Jeff Johnsone7245742012-09-05 17:12:55 -07002743 tANI_U8 type = 0;
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002744 tANI_U8 subType = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -07002745 tActionFrmType actionFrmType;
2746 hdd_cfg80211_state_t *cfgState = NULL;
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302747 hdd_scaninfo_t *pScanInfo = NULL;
Kaushik, Sushant13a287c2014-05-03 12:26:27 +05302748 hdd_context_t *pHddCtx = NULL;
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302749 VOS_STATUS status;
2750 hdd_remain_on_chan_ctx_t* pRemainChanCtx = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07002751
Agarwal Ashishae800dd2015-06-24 12:44:48 +05302752 hddLog(VOS_TRACE_LEVEL_INFO, FL("Frame Type = %d Frame Length = %d"),
2753 frameType, nFrameLength);
Jeff Johnson295189b2012-06-20 16:38:30 -07002754
2755 if (NULL == pAdapter)
2756 {
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002757 hddLog(LOGE, FL("pAdapter is NULL"));
2758 return;
2759 }
2760
2761 if (0 == nFrameLength)
2762 {
2763 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2764 return;
2765 }
2766
2767 if (NULL == pbFrames)
2768 {
2769 hddLog(LOGE, FL("pbFrames is NULL"));
Jeff Johnson295189b2012-06-20 16:38:30 -07002770 return;
2771 }
2772
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002773 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2774 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2775
2776 /* Get pAdapter from Destination mac address of the frame */
2777 if ((type == SIR_MAC_MGMT_FRAME) &&
Sreelakshmi Konamki14dccd22017-05-11 12:17:22 +05302778 (subType != SIR_MAC_MGMT_PROBE_REQ) &&
Wu Gao6518a292019-04-02 13:31:41 +08002779 (nFrameLength > WLAN_HDD_80211_FRM_DA_OFFSET + VOS_MAC_ADDR_SIZE) &&
Sreelakshmi Konamki14dccd22017-05-11 12:17:22 +05302780 !vos_is_macaddr_broadcast(
2781 (v_MACADDR_t *)&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]))
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002782 {
2783 pAdapter = hdd_get_adapter_by_macaddr( WLAN_HDD_GET_CTX(pAdapter),
2784 &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
2785 if (NULL == pAdapter)
2786 {
2787 /* Under assumtion that we don't receive any action frame
2788 * with BCST as destination we dropping action frame
2789 */
Madan Mohan Koyyalamudi051ff0b2012-12-03 16:55:26 -08002790 hddLog(VOS_TRACE_LEVEL_FATAL,"pAdapter for action frame is NULL Macaddr = "
2791 MAC_ADDRESS_STR ,
2792 MAC_ADDR_ARRAY(&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]));
2793 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Frame Type = %d Frame Length = %d"
Arif Hussain6d2a3322013-11-17 19:50:10 -08002794 " subType = %d",__func__,frameType,nFrameLength,subType);
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07002795 return;
2796 }
2797 }
2798
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002799
Jeff Johnson295189b2012-06-20 16:38:30 -07002800 if (NULL == pAdapter->dev)
2801 {
2802 hddLog( LOGE, FL("pAdapter->dev is NULL"));
2803 return;
2804 }
2805
2806 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
2807 {
2808 hddLog( LOGE, FL("pAdapter has invalid magic"));
2809 return;
2810 }
2811
Rashmi Ramannadae90e02013-12-30 21:49:48 +05302812 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2813 if (NULL == pHddCtx)
2814 {
2815 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
2816 return;
2817 }
2818
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002819 if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) ||
2820 (WLAN_HDD_P2P_GO == pAdapter->device_mode ))
Jeff Johnson295189b2012-06-20 16:38:30 -07002821 {
2822 hdd_adapter_t *pMonAdapter =
2823 hdd_get_mon_adapter( WLAN_HDD_GET_CTX(pAdapter) );
2824
Jeff Johnsonc9ca3732013-03-27 11:31:03 -07002825 if (NULL != pMonAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07002826 {
2827 hddLog( LOG1, FL("Indicate Frame over Monitor Interface"));
2828 hdd_sendMgmtFrameOverMonitorIface( pMonAdapter, nFrameLength,
2829 pbFrames, frameType);
2830 return;
2831 }
2832 }
2833
2834 //Channel indicated may be wrong. TODO
2835 //Indicate an action frame.
2836 if( rxChan <= MAX_NO_OF_2_4_CHANNELS )
2837 {
2838 freq = ieee80211_channel_to_frequency( rxChan,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302839 HDD_NL80211_BAND_2GHZ);
Jeff Johnson295189b2012-06-20 16:38:30 -07002840 }
2841 else
2842 {
2843 freq = ieee80211_channel_to_frequency( rxChan,
Rajeev Kumar Sirasanagandla5b21a9c2018-01-08 17:05:11 +05302844 HDD_NL80211_BAND_5GHZ);
Jeff Johnson295189b2012-06-20 16:38:30 -07002845 }
2846
Jeff Johnsone7245742012-09-05 17:12:55 -07002847 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
Daram Sudha1f7e0e92013-12-17 07:52:31 +05302848
2849 if ((type == SIR_MAC_MGMT_FRAME) &&
Wu Gao6518a292019-04-02 13:31:41 +08002850 (subType == SIR_MAC_MGMT_ACTION) &&
2851 (nFrameLength > WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1))
Jeff Johnsone7245742012-09-05 17:12:55 -07002852 {
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002853 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME)
2854 {
2855 // public action frame
Wu Gao6518a292019-04-02 13:31:41 +08002856 if((WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + SIR_MAC_P2P_OUI_SIZE + 2 <
2857 nFrameLength) &&
2858 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] ==
2859 SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Sudhir Sattayappa Kohallic8239802013-02-22 18:46:44 -08002860 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 -08002861 // P2P action frames
2862 {
2863 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
Arif Hussain6d2a3322013-11-17 19:50:10 -08002864 hddLog(LOG1, "Rx Action Frame %u", actionFrmType);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002865#ifdef WLAN_FEATURE_P2P_DEBUG
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002866 if(actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE)
2867 {
2868 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] <--- OTA",
2869 actionFrmType);
2870 }
2871 else
2872 {
2873 hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s <--- OTA",
2874 p2p_action_frame_type[actionFrmType]);
2875 if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
2876 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2877 {
2878 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
2879 hddLog(LOGE,"[P2P State]Inactive state to "
Jeff Johnson1250df42012-12-10 14:31:52 -08002880 "GO negotiation progress state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002881 }
2882 else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
2883 (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
2884 {
2885 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
Jeff Johnson1250df42012-12-10 14:31:52 -08002886 hddLog(LOGE,"[P2P State]GO negotiation progress to "
2887 "GO negotiation completed state");
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002888 }
2889 else if( (actionFrmType == WLAN_HDD_INVITATION_REQ) &&
2890 (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
2891 {
2892 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
2893 hddLog(LOGE,"[P2P State]Inactive state to GO negotiation"
2894 " completed state Autonomous GO formation");
2895 }
2896 }
2897#endif
Deepthi Gowri0637d592015-09-16 12:34:02 +05302898 mutex_lock(&pHddCtx->roc_lock);
2899 pRemainChanCtx = cfgState->remain_on_chan_ctx;
2900
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302901 if (pRemainChanCtx != NULL && VOS_TIMER_STATE_RUNNING
2902 == vos_timer_getCurrentState(&pRemainChanCtx->hdd_remain_on_chan_timer))
2903 {
2904 if ( actionFrmType == WLAN_HDD_GO_NEG_REQ ||
2905 actionFrmType == WLAN_HDD_GO_NEG_RESP ||
2906 actionFrmType == WLAN_HDD_INVITATION_REQ ||
2907 actionFrmType == WLAN_HDD_DEV_DIS_REQ ||
2908 actionFrmType == WLAN_HDD_PROV_DIS_REQ )
2909 {
2910 hddLog( LOG1, "Extend RoC timer on reception of"
2911 " Action Frame");
2912 if ((actionFrmType == WLAN_HDD_GO_NEG_REQ)
2913 || (actionFrmType == WLAN_HDD_GO_NEG_RESP))
2914 extend_time = 2 * ACTION_FRAME_DEFAULT_WAIT;
2915 else
2916 extend_time = ACTION_FRAME_DEFAULT_WAIT;
2917 if (completion_done(&pAdapter->rem_on_chan_ready_event))
2918 {
Deepthi Gowrif41ac8f2016-05-12 16:36:00 +05302919 if(!VOS_IS_STATUS_SUCCESS(vos_timer_stop(
2920 &pRemainChanCtx->hdd_remain_on_chan_timer)))
2921 {
2922 hddLog( LOGE, FL(
2923 "Failed to stop hdd_remain_on_chan_timer"));
2924 }
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302925 status = vos_timer_start(
2926 &pRemainChanCtx->hdd_remain_on_chan_timer,
2927 extend_time);
2928 if (status != VOS_STATUS_SUCCESS)
2929 {
2930 hddLog( LOGE, "ROC timer start failed");
2931 }
2932 }
2933 else
2934 {
2935 // Buffer Packet
2936 if (pRemainChanCtx->action_pkt_buff.frame_length == 0)
2937 {
2938 pRemainChanCtx->action_pkt_buff.frame_length =
2939 nFrameLength;
2940 pRemainChanCtx->action_pkt_buff.freq = freq;
2941 pRemainChanCtx->action_pkt_buff.frame_ptr
2942 = vos_mem_malloc(nFrameLength);
2943 vos_mem_copy(
2944 pRemainChanCtx->action_pkt_buff.frame_ptr,
2945 pbFrames, nFrameLength);
2946 hddLog( LOGE,"%s:"
2947 "Action Pkt Cached successfully !!!", __func__);
2948 }
2949 else
2950 {
2951 hddLog( LOGE,"%s:"
2952 "Frames are pending. dropping frame !!!",
2953 __func__);
2954 }
Deepthi Gowri0637d592015-09-16 12:34:02 +05302955 mutex_unlock(&pHddCtx->roc_lock);
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302956 return;
2957 }
2958 }
2959 }
2960 if (pRemainChanCtx != NULL &&
Deepthi Gowri12e2dae2015-12-07 17:32:09 +05302961 vos_timer_is_initialized(
2962 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer) &&
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302963 VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(
2964 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
2965 hddLog( LOG1, "%s:"
2966 "Rcvd action frame after timer expired ", __func__);
2967
Deepthi Gowri0637d592015-09-16 12:34:02 +05302968 mutex_unlock(&pHddCtx->roc_lock);
2969
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302970 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP) &&
2971 (cfgState->actionFrmState == HDD_PD_REQ_ACK_PENDING)) ||
2972 ((actionFrmType == WLAN_HDD_GO_NEG_RESP) &&
2973 (cfgState->actionFrmState == HDD_GO_NEG_REQ_ACK_PENDING)))
2974 {
Deepthi Gowri0637d592015-09-16 12:34:02 +05302975 hddLog(LOG1, "%s: ACK_PENDING and But received RESP for Action frame ",
Kaushik, Sushant7005e372014-04-08 11:36:54 +05302976 __func__);
Deepthi Gowri108809c2016-06-16 18:04:24 +05302977 cfgState->is_go_neg_ack_received = 1;
2978
Deepthi Gowri0637d592015-09-16 12:34:02 +05302979 hdd_sendActionCnf(pAdapter, TRUE);
2980 }
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07002981 }
Gopichand Nakkalab977a972013-02-18 19:15:09 -08002982#ifdef FEATURE_WLAN_TDLS
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002983 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 -07002984 {
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002985 u8 *mac = &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6];
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302986 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] TDLS Discovery Response," MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002987 MAC_ADDR_ARRAY(mac),rxRssi);
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05302988
Shailender Karmuchi13c0d082013-03-26 14:41:39 -07002989 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2990 wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac);
Hoonki Lee1090c6a2013-01-16 17:40:54 -08002991 }
2992#endif
2993 }
Kaushik, Sushant507a8612014-10-21 17:00:55 +05302994
2995 pScanInfo = &pHddCtx->scan_info;
2996 if ((pScanInfo != NULL) && (pHddCtx->scan_info.mScanPending))
2997 {
2998 hddLog(LOGE,"Action frame received when Scanning is in"
2999 " progress. Abort Scan.");
3000 hdd_abort_mac_scan(pAdapter->pHddCtx,
3001 pScanInfo->sessionId,
3002 eCSR_SCAN_ABORT_DEFAULT);
3003 }
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05303004
Hoonki Lee1090c6a2013-01-16 17:40:54 -08003005 if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_TDLS_ACTION_FRAME)
3006 {
3007 actionFrmType = pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1];
3008 if(actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE)
3009 {
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05303010 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] Action type[%d] <--- OTA",
Hoonki Lee1090c6a2013-01-16 17:40:54 -08003011 actionFrmType);
3012 }
3013 else
3014 {
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05303015 hddLog(VOS_TRACE_LEVEL_INFO,"[TDLS] %s <--- OTA",
Hoonki Lee1090c6a2013-01-16 17:40:54 -08003016 tdls_action_frame_type[actionFrmType]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07003017 }
Abhishek Singh888420b2016-01-06 12:28:03 +05303018 vos_tdls_tx_rx_mgmt_event(SIR_MAC_ACTION_TDLS,
3019 SIR_MAC_ACTION_RX, SIR_MAC_MGMT_ACTION,
3020 actionFrmType, &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET+6]);
Madan Mohan Koyyalamudi26bd7142012-10-30 18:14:19 -07003021 }
Masti, Narayanraddi34e0e562015-03-05 18:23:03 +05303022
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07003023 if((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_QOS_ACTION_FRAME)&&
3024 (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_QOS_MAP_CONFIGURE) )
3025 {
Kumar Anand82c009f2014-05-29 00:29:42 -07003026 sme_UpdateDSCPtoUPMapping(pHddCtx->hHal,
3027 pAdapter->hddWmmDscpToUpMap, pAdapter->sessionId);
Leela Venkata Kiran Kumar Reddy Chirala8e69fbc2013-10-30 18:51:13 -07003028 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003029 }
3030
Jeff Johnson295189b2012-06-20 16:38:30 -07003031 //Indicate Frame Over Normal Interface
3032 hddLog( LOG1, FL("Indicate Frame over NL80211 Interface"));
Anand N Sunkad7bfc8e42015-07-29 09:59:45 +05303033#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
yeshwanth sriram guntukabbdd77c2017-05-02 12:49:53 +05303034 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, rxRssi * 100, pbFrames,
Anand N Sunkad7bfc8e42015-07-29 09:59:45 +05303035 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED);
3036#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
yeshwanth sriram guntukabbdd77c2017-05-02 12:49:53 +05303037 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, rxRssi * 100, pbFrames,
Anand N Sunkade9adb1b2015-07-29 09:56:45 +05303038 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
3039#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
yeshwanth sriram guntukabbdd77c2017-05-02 12:49:53 +05303040 cfg80211_rx_mgmt( pAdapter->dev->ieee80211_ptr, freq, rxRssi * 100,
Jeff Johnson3bbe4bf2013-01-18 17:05:29 -08003041 pbFrames, nFrameLength,
3042 GFP_ATOMIC );
3043#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0))
yeshwanth sriram guntukabbdd77c2017-05-02 12:49:53 +05303044 cfg80211_rx_mgmt( pAdapter->dev, freq, rxRssi * 100,
Jeff Johnson295189b2012-06-20 16:38:30 -07003045 pbFrames, nFrameLength,
3046 GFP_ATOMIC );
3047#else
3048 cfg80211_rx_mgmt( pAdapter->dev, freq,
3049 pbFrames, nFrameLength,
3050 GFP_ATOMIC );
3051#endif //LINUX_VERSION_CODE
3052}
3053
3054/*
3055 * ieee80211_add_rx_radiotap_header - add radiotap header
3056 */
3057static int hdd_wlan_add_rx_radiotap_hdr (
3058 struct sk_buff *skb, int rtap_len, int flag )
3059{
3060 u8 rtap_temp[20] = {0};
3061 struct ieee80211_radiotap_header *rthdr;
3062 unsigned char *pos;
3063 u16 rx_flags = 0;
3064
3065 rthdr = (struct ieee80211_radiotap_header *)(&rtap_temp[0]);
3066
3067 /* radiotap header, set always present flags */
3068 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
3069 (1 << IEEE80211_RADIOTAP_RX_FLAGS));
3070 rthdr->it_len = cpu_to_le16(rtap_len);
3071
3072 pos = (unsigned char *) (rthdr + 1);
3073
3074 /* the order of the following fields is important */
3075
3076 /* IEEE80211_RADIOTAP_FLAGS */
3077 *pos = 0;
3078 pos++;
3079
3080 /* IEEE80211_RADIOTAP_RX_FLAGS: Length 2 Bytes */
3081 /* ensure 2 byte alignment for the 2 byte field as required */
3082 if ((pos - (u8 *)rthdr) & 1)
3083 pos++;
3084 put_unaligned_le16(rx_flags, pos);
3085 pos += 2;
Daram Sudha1f7e0e92013-12-17 07:52:31 +05303086
Jeff Johnson295189b2012-06-20 16:38:30 -07003087 // actually push the data
3088 memcpy(skb_push(skb, rtap_len), &rtap_temp[0], rtap_len);
3089
3090 return 0;
3091}
3092
3093static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter,
3094 hdd_cfg80211_state_t* cfgState,
3095 tANI_BOOLEAN actionSendSuccess )
3096{
3097 struct ieee80211_radiotap_header *rthdr;
3098 unsigned char *pos;
3099 struct sk_buff *skb = cfgState->skb;
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003100#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003101#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3102 hdd_context_t *pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx);
3103#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003104#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003105
3106 /* 2 Byte for TX flags and 1 Byte for Retry count */
3107 u32 rtHdrLen = sizeof(*rthdr) + 3;
3108
3109 u8 *data;
3110
3111 /* We have to return skb with Data starting with MAC header. We have
3112 * copied SKB data starting with MAC header to cfgState->buf. We will pull
3113 * entire skb->len from skb and then we will push cfgState->buf to skb
3114 * */
3115 if( NULL == skb_pull(skb, skb->len) )
3116 {
3117 hddLog( LOGE, FL("Not Able to Pull %d byte from skb"), skb->len);
3118 kfree_skb(cfgState->skb);
3119 return;
3120 }
3121
3122 data = skb_push( skb, cfgState->len );
3123
3124 if (data == NULL)
3125 {
Jeff Johnson59a121e2013-11-30 09:46:08 -08003126 hddLog( LOGE, FL("Not Able to Push %zu byte to skb"), cfgState->len);
Jeff Johnson295189b2012-06-20 16:38:30 -07003127 kfree_skb( cfgState->skb );
3128 return;
3129 }
3130
3131 memcpy( data, cfgState->buf, cfgState->len );
3132
3133 /* send frame to monitor interfaces now */
3134 if( skb_headroom(skb) < rtHdrLen )
3135 {
3136 hddLog( LOGE, FL("No headroom for rtap header"));
3137 kfree_skb(cfgState->skb);
3138 return;
3139 }
3140
3141 rthdr = (struct ieee80211_radiotap_header*) skb_push( skb, rtHdrLen );
3142
3143 memset( rthdr, 0, rtHdrLen );
3144 rthdr->it_len = cpu_to_le16( rtHdrLen );
3145 rthdr->it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
3146 (1 << IEEE80211_RADIOTAP_DATA_RETRIES)
3147 );
3148
3149 pos = (unsigned char *)( rthdr+1 );
3150
3151 // Fill TX flags
3152 *pos = actionSendSuccess;
3153 pos += 2;
3154
3155 // Fill retry count
3156 *pos = 0;
3157 pos++;
3158
3159 skb_set_mac_header( skb, 0 );
Madan Mohan Koyyalamudif91902f2012-10-25 11:59:19 -07003160 skb->ip_summed = CHECKSUM_NONE;
Jeff Johnson295189b2012-06-20 16:38:30 -07003161 skb->pkt_type = PACKET_OTHERHOST;
3162 skb->protocol = htons(ETH_P_802_2);
3163 memset( skb->cb, 0, sizeof( skb->cb ) );
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003164#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003165#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
Sushant Kaushik83392fa2015-05-05 17:44:40 +05303166 vos_wake_lock_timeout_release(&pHddCtx->rx_wake_lock,
3167 HDD_WAKE_LOCK_DURATION,
3168 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
Jeff Johnsone7245742012-09-05 17:12:55 -07003169#endif
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003170#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003171 if (in_interrupt())
3172 netif_rx( skb );
3173 else
3174 netif_rx_ni( skb );
3175
3176 /* Enable Queues which we have disabled earlier */
Padma, Santhosh Kumar9dacb5c2014-12-17 19:22:56 +05303177 hddLog(VOS_TRACE_LEVEL_INFO, FL("Enabling queues"));
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05303178 netif_tx_start_all_queues( pAdapter->dev );
Jeff Johnson295189b2012-06-20 16:38:30 -07003179
3180}
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05303181
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +05303182void __hdd_p2p_roc_work_queue(struct work_struct *work)
Ganesh Kondabattinibabfb492014-12-17 20:25:29 +05303183{
3184 hdd_adapter_t *pAdapter = container_of(to_delayed_work(work), hdd_adapter_t, roc_work);
3185 hddLog( VOS_TRACE_LEVEL_INFO, FL("%s: "), __func__);
3186 wlan_hdd_p2p_start_remain_on_channel(pAdapter);
3187 return;
3188}
3189
Mahesh A Saptasagare5440c72015-01-28 21:21:07 +05303190void hdd_p2p_roc_work_queue(struct work_struct *work)
3191{
3192 vos_ssr_protect(__func__);
3193 __hdd_p2p_roc_work_queue(work);
3194 vos_ssr_unprotect(__func__);
3195 return;
3196}