blob: 8f4d5f3d75833c2240c8b71eff2056b846303be0 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -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.
20 */
21
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
28/**
29 *
30 * @file wlan_hdd_p2p.c
31 *
32 * @brief WLAN Host Device Driver implementation for P2P commands interface
33 *
34 */
35
36#include <wlan_hdd_includes.h>
37#include <wlan_hdd_hostapd.h>
38#include <net/cfg80211.h>
39#include "sme_api.h"
40#include "sme_qos_api.h"
41#include "wlan_hdd_p2p.h"
42#include "sap_api.h"
43#include "wlan_hdd_main.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <linux/netdevice.h>
46#include <linux/skbuff.h>
47#include <linux/etherdevice.h>
48#include <net/ieee80211_radiotap.h>
49#include "wlan_hdd_tdls.h"
50#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053051#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053052#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "cds_sched.h"
54#include "cds_concurrency.h"
55
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +053056/* Ms to Time Unit Micro Sec */
57#define MS_TO_TU_MUS(x) ((x) * 1024)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080058
59static uint8_t *hdd_get_action_string(uint16_t MsgType)
60{
61 switch (MsgType) {
62 CASE_RETURN_STRING(SIR_MAC_ACTION_SPECTRUM_MGMT);
63 CASE_RETURN_STRING(SIR_MAC_ACTION_QOS_MGMT);
64 CASE_RETURN_STRING(SIR_MAC_ACTION_DLP);
65 CASE_RETURN_STRING(SIR_MAC_ACTION_PUBLIC_USAGE);
66 CASE_RETURN_STRING(SIR_MAC_ACTION_RRM);
67 CASE_RETURN_STRING(SIR_MAC_ACTION_FAST_BSS_TRNST);
68 CASE_RETURN_STRING(SIR_MAC_ACTION_HT);
69 CASE_RETURN_STRING(SIR_MAC_ACTION_SA_QUERY);
70 CASE_RETURN_STRING(SIR_MAC_ACTION_PROT_DUAL_PUB);
71 CASE_RETURN_STRING(SIR_MAC_ACTION_WNM);
72 CASE_RETURN_STRING(SIR_MAC_ACTION_UNPROT_WNM);
73 CASE_RETURN_STRING(SIR_MAC_ACTION_TDLS);
74 CASE_RETURN_STRING(SIR_MAC_ACITON_MESH);
75 CASE_RETURN_STRING(SIR_MAC_ACTION_MHF);
76 CASE_RETURN_STRING(SIR_MAC_SELF_PROTECTED);
77 CASE_RETURN_STRING(SIR_MAC_ACTION_WME);
78 CASE_RETURN_STRING(SIR_MAC_ACTION_VHT);
79 default:
80 return "UNKNOWN";
81 }
82}
83
84#ifdef WLAN_FEATURE_P2P_DEBUG
85#define MAX_P2P_ACTION_FRAME_TYPE 9
86const char *p2p_action_frame_type[] = { "GO Negotiation Request",
87 "GO Negotiation Response",
88 "GO Negotiation Confirmation",
89 "P2P Invitation Request",
90 "P2P Invitation Response",
91 "Device Discoverability Request",
92 "Device Discoverability Response",
93 "Provision Discovery Request",
94 "Provision Discovery Response"};
95
96/* We no need to protect this variable since
97 * there is no chance of race to condition
98 * and also not make any complicating the code
99 * just for debugging log
100 */
101tP2PConnectionStatus global_p2p_connection_status = P2P_NOT_ACTIVE;
102
103#endif
104#define MAX_TDLS_ACTION_FRAME_TYPE 11
105const char *tdls_action_frame_type[] = { "TDLS Setup Request",
106 "TDLS Setup Response",
107 "TDLS Setup Confirm",
108 "TDLS Teardown",
109 "TDLS Peer Traffic Indication",
110 "TDLS Channel Switch Request",
111 "TDLS Channel Switch Response",
112 "TDLS Peer PSM Request",
113 "TDLS Peer PSM Response",
114 "TDLS Peer Traffic Response",
115 "TDLS Discovery Request"};
116
117static bool wlan_hdd_is_type_p2p_action(const u8 *buf)
118{
119 const u8 *ouiPtr;
120
121 if (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET] !=
122 WLAN_HDD_PUBLIC_ACTION_FRAME) {
123 return false;
124 }
125
126 if (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET] !=
127 WLAN_HDD_VENDOR_SPECIFIC_ACTION) {
128 return false;
129 }
130
131 ouiPtr = &buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_OFFSET];
132
133 if (WPA_GET_BE24(ouiPtr) != WLAN_HDD_WFA_OUI) {
134 return false;
135 }
136
137 if (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OUI_TYPE_OFFSET] !=
138 WLAN_HDD_WFA_P2P_OUI_TYPE) {
139 return false;
140 }
141
142 return true;
143}
144
145static bool hdd_p2p_is_action_type_rsp(const u8 *buf)
146{
147 tActionFrmType actionFrmType;
148
149 if (wlan_hdd_is_type_p2p_action(buf)) {
150 actionFrmType =
151 buf[WLAN_HDD_PUBLIC_ACTION_FRAME_SUB_TYPE_OFFSET];
152 if (actionFrmType != WLAN_HDD_INVITATION_REQ
153 && actionFrmType != WLAN_HDD_GO_NEG_REQ
154 && actionFrmType != WLAN_HDD_DEV_DIS_REQ
155 && actionFrmType != WLAN_HDD_PROV_DIS_REQ)
156 return true;
157 }
158
159 return false;
160}
161
162static
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530163QDF_STATUS wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void *pCtx,
164 QDF_STATUS status, uint32_t scan_id)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165{
166 hdd_adapter_t *pAdapter = (hdd_adapter_t *) pCtx;
167 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
168 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
169 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
170
171 if (!hdd_ctx) {
172 hdd_err("Invalid HDD context");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530173 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174 }
175
176 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
177 pRemainChanCtx = cfgState->remain_on_chan_ctx;
178
179 if (pRemainChanCtx == NULL) {
180 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
181 hddLog(LOGW,
182 "%s: No Rem on channel pending for which Rsp is received",
183 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530184 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185 }
186
187 hddLog(LOG1, "Received remain on channel rsp");
Anurag Chouhan210db072016-02-22 18:42:15 +0530188 qdf_mc_timer_stop(&pRemainChanCtx->hdd_remain_on_chan_timer);
189 qdf_mc_timer_destroy(&pRemainChanCtx->hdd_remain_on_chan_timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800190
191 cfgState->remain_on_chan_ctx = NULL;
192 /*
193 * Resetting the roc in progress early ensures that the subsequent
194 * roc requests are immediately processed without being queued
195 */
196 pAdapter->is_roc_inprogress = false;
197 /*
198 * If the allow suspend is done later, the scheduled roc wil prevent
199 * the system from going into suspend and immediately this logic
200 * will allow the system to go to suspend breaking the exising logic.
201 * Basically, the system must not go into suspend while roc is in
202 * progress.
203 */
204 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
205 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
206
207 if (REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) {
208 if (cfgState->buf) {
Agrawal Ashishc38e58d2015-09-16 17:17:29 +0530209 hdd_info("We need to receive yet an ack from one of tx packet");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210 }
211 cfg80211_remain_on_channel_expired(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212 pRemainChanCtx->dev->
213 ieee80211_ptr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214 pRemainChanCtx->
215 cookie,
216 &pRemainChanCtx->chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217 GFP_KERNEL);
Anurag Chouhan210db072016-02-22 18:42:15 +0530218 pAdapter->last_roc_ts = qdf_mc_timer_get_system_time();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 }
220
221 /* Schedule any pending RoC: Any new roc request during this time
222 * would have got queued in 'wlan_hdd_request_remain_on_channel'
223 * since the queue is not empty. So, the roc at the head of the
224 * queue will only get the priority. Scheduling the work queue
225 * after sending any cancel remain on channel event will also
226 * ensure that the cancel roc is sent without any delays.
227 */
228 schedule_delayed_work(&hdd_ctx->roc_req_work, 0);
229
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800230 if ((QDF_STA_MODE == pAdapter->device_mode) ||
231 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) ||
232 (QDF_P2P_DEVICE_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233 ) {
234 uint8_t sessionId = pAdapter->sessionId;
235 if (REMAIN_ON_CHANNEL_REQUEST ==
236 pRemainChanCtx->rem_on_chan_request) {
237 sme_deregister_mgmt_frame(hHal, sessionId,
238 (SIR_MAC_MGMT_FRAME << 2) |
239 (SIR_MAC_MGMT_PROBE_REQ << 4),
240 NULL, 0);
241 }
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800242 } else if ((QDF_SAP_MODE == pAdapter->device_mode) ||
243 (QDF_P2P_GO_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800244 ) {
245 wlansap_de_register_mgmt_frame(
Dustin Brown0a1da142016-09-13 13:31:52 -0700246 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800247 (SIR_MAC_MGMT_FRAME << 2) |
Dustin Brown0a1da142016-09-13 13:31:52 -0700248 (SIR_MAC_MGMT_PROBE_REQ << 4),
249 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800250
251 }
252
253 if (pRemainChanCtx->action_pkt_buff.frame_ptr != NULL
254 && pRemainChanCtx->action_pkt_buff.frame_length != 0) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530255 qdf_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800256 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
257 pRemainChanCtx->action_pkt_buff.frame_length = 0;
258 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530259 qdf_mem_free(pRemainChanCtx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800260 complete(&pAdapter->cancel_rem_on_chan_var);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530261 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800262 complete(&pAdapter->rem_on_chan_ready_event);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530263 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800264}
265
266void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
267{
268 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
269 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
270 unsigned long rc;
271
272 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
273 if (cfgState->remain_on_chan_ctx != NULL) {
274 hddLog(LOGE, "Cancel Existing Remain on Channel");
275
Anurag Chouhan210db072016-02-22 18:42:15 +0530276 if (QDF_TIMER_STATE_RUNNING == qdf_mc_timer_get_current_state(
Anurag Chouhanffb21542016-02-17 14:33:03 +0530277 &cfgState->remain_on_chan_ctx->hdd_remain_on_chan_timer))
Anurag Chouhan210db072016-02-22 18:42:15 +0530278 qdf_mc_timer_stop(&cfgState->remain_on_chan_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 hdd_remain_on_chan_timer);
280
281 pRemainChanCtx = cfgState->remain_on_chan_ctx;
282 if (pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress ==
283 true) {
284 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
285 hddLog(LOGE,
286 "ROC timer cancellation in progress,"
287 " wait for completion");
288 rc = wait_for_completion_timeout(&pAdapter->
289 cancel_rem_on_chan_var,
290 msecs_to_jiffies
291 (WAIT_CANCEL_REM_CHAN));
292 if (!rc) {
293 hddLog(LOGE,
294 "%s:wait on cancel_rem_on_chan_var timed out",
295 __func__);
296 }
297 return;
298 }
299 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = true;
300 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
301 /* Wait till remain on channel ready indication before issuing cancel
302 * remain on channel request, otherwise if remain on channel not
303 * received and if the driver issues cancel remain on channel then lim
304 * will be in unknown state.
305 */
306 rc = wait_for_completion_timeout(&pAdapter->
307 rem_on_chan_ready_event,
308 msecs_to_jiffies
309 (WAIT_REM_CHAN_READY));
310 if (!rc) {
311 hddLog(LOGE,
312 "%s: timeout waiting for remain on channel ready indication",
313 __func__);
Abhishek Singh5ea86532016-04-27 14:10:53 +0530314 cds_flush_logs(WLAN_LOG_TYPE_FATAL,
315 WLAN_LOG_INDICATOR_HOST_DRIVER,
316 WLAN_LOG_REASON_HDD_TIME_OUT,
317 true, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800318 }
319
320 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
321
322 /* Issue abort remain on chan request to sme.
323 * The remain on channel callback will make sure the remain_on_chan
324 * expired event is sent.
325 */
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800326 if ((QDF_STA_MODE == pAdapter->device_mode) ||
327 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) ||
328 (QDF_P2P_DEVICE_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800329 ) {
330 sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX
331 (pAdapter),
332 pAdapter->sessionId,
333 pRemainChanCtx->scan_id);
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800334 } else if ((QDF_SAP_MODE == pAdapter->device_mode)
335 || (QDF_P2P_GO_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800336 ) {
337 wlansap_cancel_remain_on_channel(
Dustin Brown0a1da142016-09-13 13:31:52 -0700338 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
339 pRemainChanCtx->scan_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340 }
341
342 rc = wait_for_completion_timeout(&pAdapter->
343 cancel_rem_on_chan_var,
344 msecs_to_jiffies
345 (WAIT_CANCEL_REM_CHAN));
346
347 if (!rc) {
348 hddLog(LOGE,
349 "%s: timeout waiting for cancel remain on channel ready"
350 " indication", __func__);
351 }
352 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
353 } else
354 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
355}
356
357int wlan_hdd_check_remain_on_channel(hdd_adapter_t *pAdapter)
358{
359 int status = 0;
360 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
361
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800362 if (QDF_P2P_GO_MODE != pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363 /* Cancel Existing Remain On Channel */
364 /* If no action frame is pending */
365 if (cfgState->remain_on_chan_ctx != NULL) {
366 /* Check whether Action Frame is pending or not */
367 if (cfgState->buf == NULL) {
368 wlan_hdd_cancel_existing_remain_on_channel
369 (pAdapter);
370 } else {
371 hddLog(LOG1,
372 "Cannot Cancel Existing Remain on Channel");
373 status = -EBUSY;
374 }
375 }
376 }
377 return status;
378}
379
380/**
381 * wlan_hdd_cancel_pending_roc() - Cancel pending roc
382 * @adapter: HDD adapter
383 *
384 * Cancels any pending remain on channel request
385 *
386 * Return: None
387 */
388void wlan_hdd_cancel_pending_roc(hdd_adapter_t *adapter)
389{
390 hdd_remain_on_chan_ctx_t *roc_ctx;
391 unsigned long rc;
392 hdd_cfg80211_state_t *cfg_state = WLAN_HDD_GET_CFG_STATE_PTR(adapter);
393
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530394 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800395 "%s: ROC completion is not received.!!!",
396 __func__);
397
398 mutex_lock(&cfg_state->remain_on_chan_ctx_lock);
399 roc_ctx = cfg_state->remain_on_chan_ctx;
400
401 if (roc_ctx->hdd_remain_on_chan_cancel_in_progress) {
402 mutex_unlock(&cfg_state->remain_on_chan_ctx_lock);
403 hdd_debug("roc cancel already in progress");
404 /*
405 * Since a cancel roc is already issued and is
406 * in progress, we need not send another
407 * cancel roc again. Instead we can just wait
408 * for cancel roc completion
409 */
410 goto wait;
411 }
412 mutex_unlock(&cfg_state->remain_on_chan_ctx_lock);
413
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800414 if (adapter->device_mode == QDF_P2P_GO_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415 wlansap_cancel_remain_on_channel((WLAN_HDD_GET_CTX
416 (adapter))->pcds_context,
417 cfg_state->remain_on_chan_ctx->scan_id);
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800418 } else if (adapter->device_mode == QDF_P2P_CLIENT_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800419 || adapter->device_mode ==
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800420 QDF_P2P_DEVICE_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800421 sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX
422 (adapter),
423 adapter->sessionId,
424 cfg_state->remain_on_chan_ctx->scan_id);
425 }
426
427wait:
428 rc = wait_for_completion_timeout(&adapter->cancel_rem_on_chan_var,
429 msecs_to_jiffies
430 (WAIT_CANCEL_REM_CHAN));
431 if (!rc) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530432 QDF_TRACE(QDF_MODULE_ID_HDD,
433 QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800434 "%s: Timeout occurred while waiting for RoC Cancellation",
435 __func__);
436 mutex_lock(&cfg_state->remain_on_chan_ctx_lock);
437 roc_ctx = cfg_state->remain_on_chan_ctx;
438 if (roc_ctx != NULL) {
439 cfg_state->remain_on_chan_ctx = NULL;
Anurag Chouhan210db072016-02-22 18:42:15 +0530440 qdf_mc_timer_stop(&roc_ctx->hdd_remain_on_chan_timer);
441 qdf_mc_timer_destroy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800442 &roc_ctx->hdd_remain_on_chan_timer);
443 if (roc_ctx->action_pkt_buff.frame_ptr != NULL
444 && roc_ctx->action_pkt_buff.frame_length != 0) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530445 qdf_mem_free(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800446 roc_ctx->action_pkt_buff.frame_ptr);
447 roc_ctx->action_pkt_buff.frame_ptr = NULL;
448 roc_ctx->action_pkt_buff.frame_length = 0;
449 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530450 qdf_mem_free(roc_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800451 adapter->is_roc_inprogress = false;
452 }
453 mutex_unlock(&cfg_state->remain_on_chan_ctx_lock);
454 }
455}
456
457/* Clean up RoC context at hdd_stop_adapter*/
458void wlan_hdd_cleanup_remain_on_channel_ctx(hdd_adapter_t *pAdapter)
459{
460 uint8_t retry = 0;
461 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
462
463 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
464 while (pAdapter->is_roc_inprogress) {
465 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530466 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800467 "%s: ROC in progress for session %d!!!",
468 __func__, pAdapter->sessionId);
469 msleep(500);
470 if (retry++ > 3) {
471 wlan_hdd_cancel_pending_roc(pAdapter);
472 /* hold the lock before break from the loop */
473 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
474 break;
475 }
476 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
477 } /* end of while */
478 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
479
480}
481
482void wlan_hdd_remain_on_chan_timeout(void *data)
483{
484 hdd_adapter_t *pAdapter = (hdd_adapter_t *) data;
485 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
486 hdd_cfg80211_state_t *cfgState;
487
c_hpothud5009242016-08-18 12:10:36 +0530488 if ((NULL == pAdapter) ||
489 (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)) {
490 hdd_err("pAdapter is invalid %p !!!", pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800491 return;
492 }
493
494 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
495 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
496 pRemainChanCtx = cfgState->remain_on_chan_ctx;
497
498 if (NULL == pRemainChanCtx) {
499 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
500 hddLog(LOGE, "%s: No Remain on channel is pending", __func__);
501 return;
502 }
503
504 if (true == pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress) {
505 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
506 hddLog(LOGE, FL("Cancellation already in progress"));
507 return;
508 }
509
510 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = true;
511 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
512 hddLog(LOG1, "%s: Cancel Remain on Channel on timeout", __func__);
513
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800514 if ((QDF_STA_MODE == pAdapter->device_mode) ||
515 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) ||
516 (QDF_P2P_DEVICE_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 ) {
518 sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX(pAdapter),
519 pAdapter->sessionId,
520 pRemainChanCtx->scan_id);
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800521 } else if ((QDF_SAP_MODE == pAdapter->device_mode) ||
522 (QDF_P2P_GO_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800523 ) {
524 wlansap_cancel_remain_on_channel(
525 (WLAN_HDD_GET_CTX(pAdapter))->pcds_context,
526 pRemainChanCtx->scan_id);
527 }
528
529 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
530
531}
532
533static int wlan_hdd_execute_remain_on_channel(hdd_adapter_t *pAdapter,
534 hdd_remain_on_chan_ctx_t *pRemainChanCtx)
535{
536 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530537 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
539 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
540 hdd_adapter_t *pAdapter_temp;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530541 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800542 bool isGoPresent = false;
543 unsigned int duration;
544
545
546 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
547 if (pAdapter->is_roc_inprogress == true) {
548 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530549 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 FL("remain on channel request is in execution"));
551 return -EBUSY;
552 }
553
554 cfgState->remain_on_chan_ctx = pRemainChanCtx;
555 cfgState->current_freq = pRemainChanCtx->chan.center_freq;
556 pAdapter->is_roc_inprogress = true;
557 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
558
559 /* Initialize Remain on chan timer */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530560 qdf_status =
Anurag Chouhan210db072016-02-22 18:42:15 +0530561 qdf_mc_timer_init(&pRemainChanCtx->hdd_remain_on_chan_timer,
Anurag Chouhan6d760662016-02-20 16:05:43 +0530562 QDF_TIMER_TYPE_SW,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800563 wlan_hdd_remain_on_chan_timeout, pAdapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530564 if (qdf_status != QDF_STATUS_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530565 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 FL("Not able to initialize remain_on_chan timer"));
567 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
568 cfgState->remain_on_chan_ctx = NULL;
569 pAdapter->is_roc_inprogress = false;
570 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530571 qdf_mem_free(pRemainChanCtx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572 return -EINVAL;
573 }
574
575 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530576 while (NULL != pAdapterNode && QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800577 pAdapter_temp = pAdapterNode->pAdapter;
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800578 if (pAdapter_temp->device_mode == QDF_P2P_GO_MODE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579 isGoPresent = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800580 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
581 pAdapterNode = pNext;
582 }
583
584 /* Extending duration for proactive extension logic for RoC */
585 duration = pRemainChanCtx->duration;
586 if (isGoPresent == true)
587 duration = P2P_ROC_DURATION_MULTIPLIER_GO_PRESENT * duration;
588 else
589 duration = P2P_ROC_DURATION_MULTIPLIER_GO_ABSENT * duration;
590
591 hdd_prevent_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
592 INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);
593
594 /* call sme API to start remain on channel. */
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800595 if ((QDF_STA_MODE == pAdapter->device_mode) ||
596 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) ||
597 (QDF_P2P_DEVICE_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800598 ) {
599 uint8_t sessionId = pAdapter->sessionId;
600 /* call sme API to start remain on channel. */
601
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530602 if (QDF_STATUS_SUCCESS != sme_remain_on_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800603 WLAN_HDD_GET_HAL_CTX(pAdapter),
604 sessionId,
605 pRemainChanCtx->chan.hw_value, duration,
606 wlan_hdd_remain_on_channel_callback,
607 pAdapter,
608 (pRemainChanCtx->rem_on_chan_request ==
609 REMAIN_ON_CHANNEL_REQUEST) ? true : false,
610 &pRemainChanCtx->scan_id)) {
611 hddLog(LOGE, FL("sme_remain_on_channel failed"));
612 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
613 cfgState->remain_on_chan_ctx = NULL;
614 pAdapter->is_roc_inprogress = false;
615 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +0530616 qdf_mc_timer_destroy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800617 &pRemainChanCtx->hdd_remain_on_chan_timer);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530618 qdf_mem_free(pRemainChanCtx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
620 return -EINVAL;
621 }
622
623 if (REMAIN_ON_CHANNEL_REQUEST ==
624 pRemainChanCtx->rem_on_chan_request) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530625 if (QDF_STATUS_SUCCESS != sme_register_mgmt_frame(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626 WLAN_HDD_GET_HAL_CTX(pAdapter),
627 sessionId,
628 (SIR_MAC_MGMT_FRAME << 2) |
629 (SIR_MAC_MGMT_PROBE_REQ << 4),
630 NULL, 0))
631 hddLog(LOGE,
632 FL("sme_register_mgmt_frame failed"));
633 }
634
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800635 } else if ((QDF_SAP_MODE == pAdapter->device_mode) ||
636 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800637 /* call sme API to start remain on channel. */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530638 if (QDF_STATUS_SUCCESS != wlansap_remain_on_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800639 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640 pRemainChanCtx->chan.hw_value,
641 duration, wlan_hdd_remain_on_channel_callback,
642 pAdapter, &pRemainChanCtx->scan_id)) {
643 hddLog(LOGE, FL("wlansap_remain_on_channel failed"));
644 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
645 cfgState->remain_on_chan_ctx = NULL;
646 pAdapter->is_roc_inprogress = false;
647 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
Anurag Chouhan210db072016-02-22 18:42:15 +0530648 qdf_mc_timer_destroy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 &pRemainChanCtx->hdd_remain_on_chan_timer);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530650 qdf_mem_free(pRemainChanCtx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800651 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
652 return -EINVAL;
653 }
654
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530655 if (QDF_STATUS_SUCCESS != wlansap_register_mgmt_frame(
Dustin Brown0a1da142016-09-13 13:31:52 -0700656 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657 (SIR_MAC_MGMT_FRAME << 2) |
658 (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530659 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800660 FL("wlansap_register_mgmt_frame return fail"));
661 wlansap_cancel_remain_on_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
Dustin Brown0a1da142016-09-13 13:31:52 -0700663 pRemainChanCtx->scan_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
665 return -EINVAL;
666 }
667
668 }
669 return 0;
670}
671
672/**
673 * wlan_hdd_roc_request_enqueue() - enqueue remain on channel request
674 * @adapter: Pointer to the adapter
675 * @remain_chan_ctx: Pointer to the remain on channel context
676 *
677 * Return: 0 on success, error number otherwise
678 */
679static int wlan_hdd_roc_request_enqueue(hdd_adapter_t *adapter,
680 hdd_remain_on_chan_ctx_t *remain_chan_ctx)
681{
682 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
683 hdd_roc_req_t *hdd_roc_req;
Anurag Chouhanffb21542016-02-17 14:33:03 +0530684 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685
686 /*
687 * "Driver is busy" OR "there is already RoC request inside the queue"
688 * so enqueue this RoC Request and execute sequentially later.
689 */
690
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530691 hdd_roc_req = qdf_mem_malloc(sizeof(*hdd_roc_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692
693 if (NULL == hdd_roc_req) {
694 hddLog(LOGP, FL("malloc failed for roc req context"));
695 return -ENOMEM;
696 }
697
698 hdd_roc_req->pAdapter = adapter;
699 hdd_roc_req->pRemainChanCtx = remain_chan_ctx;
700
701 /* Enqueue this RoC request */
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530702 qdf_spin_lock(&hdd_ctx->hdd_roc_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +0530703 status = qdf_list_insert_back(&hdd_ctx->hdd_roc_req_q,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 &hdd_roc_req->node);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530705 qdf_spin_unlock(&hdd_ctx->hdd_roc_req_q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706
Anurag Chouhanffb21542016-02-17 14:33:03 +0530707 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 hddLog(LOGP, FL("Not able to enqueue RoC Req context"));
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530709 qdf_mem_free(hdd_roc_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 return -EINVAL;
711 }
712
713 return 0;
714}
715
716/**
717 * wlan_hdd_indicate_roc_drop() - Indicate roc drop to userspace
718 * @adapter: HDD adapter
719 * @ctx: Remain on channel context
720 *
721 * Send remain on channel ready and cancel event for the queued
722 * roc that is being dropped. This will ensure that the userspace
723 * will send more roc requests. If this drop is not indicated to
724 * userspace, subsequent roc will not be sent to the driver since
725 * the userspace times out waiting for the remain on channel ready
726 * event.
727 *
728 * Return: None
729 */
730void wlan_hdd_indicate_roc_drop(hdd_adapter_t *adapter,
731 hdd_remain_on_chan_ctx_t *ctx)
732{
733 hdd_debug("indicate roc drop to userspace");
734 cfg80211_ready_on_channel(
735 adapter->dev->ieee80211_ptr,
736 (uintptr_t)ctx,
737 &ctx->chan,
738 ctx->duration, GFP_KERNEL);
739
740 cfg80211_remain_on_channel_expired(
741 ctx->dev->ieee80211_ptr,
742 ctx->cookie,
743 &ctx->chan,
744 GFP_KERNEL);
745}
746
747/**
748 * wlan_hdd_roc_request_dequeue() - dequeue remain on channel request
749 * @work: Pointer to work queue struct
750 *
751 * Return: none
752 */
753void wlan_hdd_roc_request_dequeue(struct work_struct *work)
754{
Anurag Chouhanffb21542016-02-17 14:33:03 +0530755 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800756 int ret = 0;
757 hdd_roc_req_t *hdd_roc_req;
758 hdd_context_t *hdd_ctx =
759 container_of(work, hdd_context_t, roc_req_work.work);
760
761 hdd_debug("going to dequeue roc");
762
763 if (0 != (wlan_hdd_validate_context(hdd_ctx)))
764 return;
765
766 /*
767 * The queued roc requests is dequeued and processed one at a time.
768 * Callback 'wlan_hdd_remain_on_channel_callback' ensures
769 * that any pending roc in the queue will be scheduled
770 * on the current roc completion by scheduling the work queue.
771 */
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530772 qdf_spin_lock(&hdd_ctx->hdd_roc_req_q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 if (list_empty(&hdd_ctx->hdd_roc_req_q.anchor)) {
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530774 qdf_spin_unlock(&hdd_ctx->hdd_roc_req_q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 return;
776 }
Anurag Chouhanffb21542016-02-17 14:33:03 +0530777 status = qdf_list_remove_front(&hdd_ctx->hdd_roc_req_q,
778 (qdf_list_node_t **) &hdd_roc_req);
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530779 qdf_spin_unlock(&hdd_ctx->hdd_roc_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +0530780 if (QDF_STATUS_SUCCESS != status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781 hdd_debug("unable to remove roc element from list");
782 return;
783 }
784 ret = wlan_hdd_execute_remain_on_channel(
785 hdd_roc_req->pAdapter,
786 hdd_roc_req->pRemainChanCtx);
787 if (ret == -EBUSY) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530788 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800789 FL("dropping RoC request"));
790 wlan_hdd_indicate_roc_drop(hdd_roc_req->pAdapter,
791 hdd_roc_req->pRemainChanCtx);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530792 qdf_mem_free(hdd_roc_req->pRemainChanCtx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530794 qdf_mem_free(hdd_roc_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800795}
796
797static int wlan_hdd_request_remain_on_channel(struct wiphy *wiphy,
798 struct net_device *dev,
799 struct ieee80211_channel *chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800800 unsigned int duration,
801 u64 *cookie,
802 rem_on_channel_request_type_t
803 request_type)
804{
805 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
806 hdd_context_t *pHddCtx;
807 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
808 bool isBusy = false;
809 uint32_t size = 0;
810 hdd_adapter_t *sta_adapter;
811 int ret;
812 int status = 0;
813
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530814 ENTER();
815
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800816 hddLog(LOG1, FL("Device_mode %s(%d)"),
817 hdd_device_mode_to_string(pAdapter->device_mode),
818 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 hddLog(LOG1,
820 "chan(hw_val)0x%x chan(centerfreq) %d, duration %d",
821 chan->hw_value, chan->center_freq, duration);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
823 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530824 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 return ret;
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -0800826 if (cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800827 hddLog(LOGE, FL("Connection is in progress"));
828 isBusy = true;
829 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530830 pRemainChanCtx = qdf_mem_malloc(sizeof(hdd_remain_on_chan_ctx_t));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800831 if (NULL == pRemainChanCtx) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530832 hddLog(QDF_TRACE_LEVEL_FATAL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833 "%s: Not able to allocate memory for Channel context",
834 __func__);
835 return -ENOMEM;
836 }
837
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530838 qdf_mem_zero(pRemainChanCtx, sizeof(*pRemainChanCtx));
839 qdf_mem_copy(&pRemainChanCtx->chan, chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840 sizeof(struct ieee80211_channel));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800841 pRemainChanCtx->duration = duration;
842 pRemainChanCtx->dev = dev;
843 *cookie = (uintptr_t) pRemainChanCtx;
844 pRemainChanCtx->cookie = *cookie;
845 pRemainChanCtx->rem_on_chan_request = request_type;
846 pRemainChanCtx->action_pkt_buff.freq = 0;
847 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
848 pRemainChanCtx->action_pkt_buff.frame_length = 0;
849 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress = false;
850 if (REMAIN_ON_CHANNEL_REQUEST == request_type) {
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800851 sta_adapter = hdd_get_adapter(pHddCtx, QDF_STA_MODE);
Anurag Chouhanffb21542016-02-17 14:33:03 +0530852 if ((NULL != sta_adapter) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853 hdd_conn_is_connected(
854 WLAN_HDD_GET_STATION_CTX_PTR(sta_adapter))) {
Anurag Chouhanffb21542016-02-17 14:33:03 +0530855 if (pAdapter->last_roc_ts != 0 &&
Anurag Chouhan210db072016-02-22 18:42:15 +0530856 ((qdf_mc_timer_get_system_time() -
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800857 pAdapter->last_roc_ts) <
858 pHddCtx->config->p2p_listen_defer_interval)) {
859 if (pRemainChanCtx->duration > HDD_P2P_MAX_ROC_DURATION)
860 pRemainChanCtx->duration =
861 HDD_P2P_MAX_ROC_DURATION;
862
863 wlan_hdd_roc_request_enqueue(pAdapter, pRemainChanCtx);
864 schedule_delayed_work(&pHddCtx->roc_req_work,
865 msecs_to_jiffies(
866 pHddCtx->config->p2p_listen_defer_interval));
867 hddLog(LOG1, "Defer interval is %hu, pAdapter %p",
868 pHddCtx->config->p2p_listen_defer_interval,
869 pAdapter);
870 return 0;
871 }
872 }
873 }
874
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530875 qdf_spin_lock(&pHddCtx->hdd_roc_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +0530876 size = qdf_list_size(&(pHddCtx->hdd_roc_req_q));
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530877 qdf_spin_unlock(&pHddCtx->hdd_roc_req_q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800878 if ((isBusy == false) && (!size)) {
879 status = wlan_hdd_execute_remain_on_channel(pAdapter,
880 pRemainChanCtx);
881 if (status == -EBUSY) {
882 if (wlan_hdd_roc_request_enqueue(pAdapter,
883 pRemainChanCtx)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530884 qdf_mem_free(pRemainChanCtx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800885 return -EAGAIN;
886 }
887 }
888 return 0;
889 } else {
890 if (wlan_hdd_roc_request_enqueue(pAdapter, pRemainChanCtx)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530891 qdf_mem_free(pRemainChanCtx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800892 return -EAGAIN;
893 }
894 }
895
896 /*
897 * If a connection is not in progress (isBusy), before scheduling
898 * the work queue it is necessary to check if a roc in in progress
899 * or not because: if an roc is in progress, the dequeued roc
900 * that will be processed will be dropped. To ensure that this new
901 * roc request is not dropped, it is suggested to check if an roc
902 * is in progress or not. The existing roc completion will provide
903 * the trigger to dequeue the next roc request.
904 */
905 if (isBusy == false && pAdapter->is_roc_inprogress == false) {
906 hdd_debug("scheduling delayed work: no connection/roc active");
907 schedule_delayed_work(&pHddCtx->roc_req_work, 0);
908 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530909 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800910 return 0;
911}
912
913int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800915 struct ieee80211_channel *chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800916 unsigned int duration, u64 *cookie)
917{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800918 struct net_device *dev = wdev->netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800919 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
920 hdd_context_t *hdd_ctx;
921 int ret;
922
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530923 ENTER();
924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800925 hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
926 ret = wlan_hdd_validate_context(hdd_ctx);
927 if (0 != ret)
928 return ret;
929
Anurag Chouhan6d760662016-02-20 16:05:43 +0530930 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800931 hddLog(LOGE, FL("Command not allowed in FTM mode"));
932 return -EINVAL;
933 }
934
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530935 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800936 TRACE_CODE_HDD_REMAIN_ON_CHANNEL,
937 pAdapter->sessionId, REMAIN_ON_CHANNEL_REQUEST));
Amar Singhal01098f72015-10-08 11:55:32 -0700938
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530939 ret = wlan_hdd_request_remain_on_channel(wiphy, dev, chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800940 duration, cookie,
941 REMAIN_ON_CHANNEL_REQUEST);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530942 EXIT();
943 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944}
945
946int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800947 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800948 struct ieee80211_channel *chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800949 unsigned int duration, u64 *cookie)
950{
951 int ret;
952
953 cds_ssr_protect(__func__);
954 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800955 wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800956 chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800957 duration, cookie);
958 cds_ssr_unprotect(__func__);
959
960 return ret;
961}
962
963void hdd_remain_chan_ready_handler(hdd_adapter_t *pAdapter,
964 uint32_t scan_id)
965{
966 hdd_cfg80211_state_t *cfgState = NULL;
967 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530968 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969
970 if (NULL == pAdapter) {
971 hddLog(LOGE, FL("pAdapter is NULL"));
972 return;
973 }
974 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
975 hddLog(LOG1, "Ready on chan ind %d", scan_id);
976
Anurag Chouhan210db072016-02-22 18:42:15 +0530977 pAdapter->start_roc_ts = qdf_mc_timer_get_system_time();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800978 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
979 pRemainChanCtx = cfgState->remain_on_chan_ctx;
980 if (pRemainChanCtx != NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530981 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800982 TRACE_CODE_HDD_REMAINCHANREADYHANDLER,
983 pAdapter->sessionId,
984 pRemainChanCtx->duration));
985 /* start timer for actual duration */
Anurag Chouhan210db072016-02-22 18:42:15 +0530986 if (QDF_TIMER_STATE_RUNNING ==
987 qdf_mc_timer_get_current_state(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988 &pRemainChanCtx->hdd_remain_on_chan_timer)) {
989 hddLog(LOGE, "Timer Started before ready event!!!");
Anurag Chouhan210db072016-02-22 18:42:15 +0530990 qdf_mc_timer_stop(&pRemainChanCtx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991 hdd_remain_on_chan_timer);
992 }
993 status =
Anurag Chouhan210db072016-02-22 18:42:15 +0530994 qdf_mc_timer_start(&pRemainChanCtx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800995 hdd_remain_on_chan_timer,
996 (pRemainChanCtx->duration +
997 COMPLETE_EVENT_PROPOGATE_TIME));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530998 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800999 hddLog(LOGE, "%s: Remain on Channel timer start failed",
1000 __func__);
1001 }
1002
1003 if (REMAIN_ON_CHANNEL_REQUEST ==
1004 pRemainChanCtx->rem_on_chan_request) {
1005 cfg80211_ready_on_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001006 pAdapter->dev->
1007 ieee80211_ptr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001008 (uintptr_t)
1009 pRemainChanCtx,
1010 &pRemainChanCtx->chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001011 pRemainChanCtx->
1012 duration, GFP_KERNEL);
1013 } else if (OFF_CHANNEL_ACTION_TX ==
1014 pRemainChanCtx->rem_on_chan_request) {
1015 complete(&pAdapter->offchannel_tx_event);
1016 }
1017 /* Check for cached action frame */
1018 if (pRemainChanCtx->action_pkt_buff.frame_length != 0) {
1019 hddLog(LOGE,
1020 "%s: Sent cached action frame to supplicant",
1021 __func__);
1022#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
1023 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr,
1024 pRemainChanCtx->action_pkt_buff.freq, 0,
1025 pRemainChanCtx->action_pkt_buff.frame_ptr,
1026 pRemainChanCtx->action_pkt_buff.frame_length,
1027 NL80211_RXMGMT_FLAG_ANSWERED);
1028#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
1029 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr,
1030 pRemainChanCtx->action_pkt_buff.freq, 0,
1031 pRemainChanCtx->action_pkt_buff.frame_ptr,
1032 pRemainChanCtx->action_pkt_buff.frame_length,
1033 NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
Amar Singhal01098f72015-10-08 11:55:32 -07001034#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001035 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr,
1036 pRemainChanCtx->action_pkt_buff.freq,
1037 0,
1038 pRemainChanCtx->action_pkt_buff.
1039 frame_ptr,
1040 pRemainChanCtx->action_pkt_buff.
1041 frame_length, GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001042#endif /* LINUX_VERSION_CODE */
1043
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301044 qdf_mem_free(pRemainChanCtx->action_pkt_buff.frame_ptr);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001045 pRemainChanCtx->action_pkt_buff.frame_length = 0;
1046 pRemainChanCtx->action_pkt_buff.freq = 0;
1047 pRemainChanCtx->action_pkt_buff.frame_ptr = NULL;
1048 }
1049 complete(&pAdapter->rem_on_chan_ready_event);
1050 } else {
1051 hddLog(LOGW, "%s: No Pending Remain on channel Request",
1052 __func__);
1053 }
1054 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
1055 return;
1056}
1057
1058int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001059 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001060 u64 cookie)
1061{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001062 struct net_device *dev = wdev->netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1064 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
1065 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
1066 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1067 int status;
Anurag Chouhanffb21542016-02-17 14:33:03 +05301068 int qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001069 unsigned long rc;
Anurag Chouhanffb21542016-02-17 14:33:03 +05301070 qdf_list_node_t *tmp, *q;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 hdd_roc_req_t *curr_roc_req;
1072
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301073 ENTER();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074
Anurag Chouhan6d760662016-02-20 16:05:43 +05301075 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001076 hddLog(LOGE, FL("Command not allowed in FTM mode"));
1077 return -EINVAL;
1078 }
1079
1080 status = wlan_hdd_validate_context(pHddCtx);
1081
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301082 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001083 return status;
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301084 qdf_spin_lock(&pHddCtx->hdd_roc_req_q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001085 list_for_each_safe(tmp, q, &pHddCtx->hdd_roc_req_q.anchor) {
1086 curr_roc_req = list_entry(tmp, hdd_roc_req_t, node);
1087 if ((uintptr_t) curr_roc_req->pRemainChanCtx == cookie) {
Anurag Chouhanffb21542016-02-17 14:33:03 +05301088 qdf_status = qdf_list_remove_node(&pHddCtx->hdd_roc_req_q,
1089 (qdf_list_node_t *)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001090 curr_roc_req);
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301091 qdf_spin_unlock(&pHddCtx->hdd_roc_req_q_lock);
Anurag Chouhanffb21542016-02-17 14:33:03 +05301092 if (qdf_status == QDF_STATUS_SUCCESS) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301093 qdf_mem_free(curr_roc_req->pRemainChanCtx);
1094 qdf_mem_free(curr_roc_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001095 }
1096 return 0;
1097 }
1098 }
Anurag Chouhana37b5b72016-02-21 14:53:42 +05301099 qdf_spin_unlock(&pHddCtx->hdd_roc_req_q_lock);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001100 /* FIXME cancel currently running remain on chan.
1101 * Need to check cookie and cancel accordingly
1102 */
1103 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
1104 pRemainChanCtx = cfgState->remain_on_chan_ctx;
1105 if ((cfgState->remain_on_chan_ctx == NULL) ||
1106 (cfgState->remain_on_chan_ctx->cookie != cookie)) {
1107 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
1108 hddLog(LOGE,
1109 "%s: No Remain on channel pending with specified cookie value",
1110 __func__);
1111 return -EINVAL;
1112 }
1113
1114 if (NULL != cfgState->remain_on_chan_ctx) {
Anurag Chouhan210db072016-02-22 18:42:15 +05301115 qdf_mc_timer_stop(&cfgState->remain_on_chan_ctx->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001116 hdd_remain_on_chan_timer);
1117 if (true ==
1118 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress) {
1119 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
1120 hddLog(LOG1,
1121 FL("ROC timer cancellation in progress,"
1122 " wait for completion"));
1123 rc = wait_for_completion_timeout(&pAdapter->
1124 cancel_rem_on_chan_var,
1125 msecs_to_jiffies
1126 (WAIT_CANCEL_REM_CHAN));
1127 if (!rc) {
1128 hddLog(LOGE,
1129 "%s:wait on cancel_rem_on_chan_var timed out",
1130 __func__);
1131 }
1132 return 0;
1133 } else
1134 pRemainChanCtx->hdd_remain_on_chan_cancel_in_progress =
1135 true;
1136 }
1137 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
1138
1139 /* wait until remain on channel ready event received
1140 * for already issued remain on channel request */
1141 rc = wait_for_completion_timeout(&pAdapter->rem_on_chan_ready_event,
1142 msecs_to_jiffies(WAIT_REM_CHAN_READY));
1143 if (!rc) {
1144 hddLog(LOGE,
1145 "%s: timeout waiting for remain on channel ready indication",
1146 __func__);
1147
Prashanth Bhatta9e143052015-12-04 11:56:47 -08001148 if (cds_is_driver_recovering()) {
1149 hdd_err("Recovery in Progress. State: 0x%x Ignore!!!",
1150 cds_get_driver_state());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001151 return -EAGAIN;
1152 }
Abhishek Singh5ea86532016-04-27 14:10:53 +05301153 cds_flush_logs(WLAN_LOG_TYPE_FATAL,
1154 WLAN_LOG_INDICATOR_HOST_DRIVER,
1155 WLAN_LOG_REASON_HDD_TIME_OUT,
1156 true, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001157 }
1158 INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
1159 /* Issue abort remain on chan request to sme.
1160 * The remain on channel callback will make sure the remain_on_chan
1161 * expired event is sent.
1162 */
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001163 if ((QDF_STA_MODE == pAdapter->device_mode) ||
1164 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) ||
1165 (QDF_P2P_DEVICE_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001166 ) {
1167
1168 uint8_t sessionId = pAdapter->sessionId;
1169 sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX(pAdapter),
1170 sessionId,
1171 pRemainChanCtx->scan_id);
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001172 } else if ((QDF_SAP_MODE == pAdapter->device_mode) ||
1173 (QDF_P2P_GO_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001174 ) {
1175 wlansap_cancel_remain_on_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001176 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001177 pRemainChanCtx->scan_id);
1178
1179 } else {
1180 hddLog(LOGE, FL("Invalid device_mode %s(%d)"),
1181 hdd_device_mode_to_string(pAdapter->device_mode),
1182 pAdapter->device_mode);
1183 return -EIO;
1184 }
1185 rc = wait_for_completion_timeout(&pAdapter->cancel_rem_on_chan_var,
1186 msecs_to_jiffies
1187 (WAIT_CANCEL_REM_CHAN));
1188 if (!rc) {
1189 hddLog(LOGE,
1190 "%s:wait on cancel_rem_on_chan_var timed out ",
1191 __func__);
1192 }
1193 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_ROC);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301194 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001195 return 0;
1196}
1197
1198int wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001199 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001200 u64 cookie)
1201{
1202 int ret;
1203
1204 cds_ssr_protect(__func__);
1205 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206 wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207 cookie);
1208 cds_ssr_unprotect(__func__);
1209
1210 return ret;
1211}
1212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
1214 struct ieee80211_channel *chan, bool offchan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 unsigned int wait,
1216 const u8 *buf, size_t len, bool no_cck,
1217 bool dont_wait_for_ack, u64 *cookie)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 struct net_device *dev = wdev->netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001220 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1221 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
1222 hdd_remain_on_chan_ctx_t *pRemainChanCtx;
1223 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1224 uint16_t extendedWait = 0;
1225 uint8_t type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
1226 uint8_t subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
1227 tActionFrmType actionFrmType;
1228 bool noack = 0;
1229 int status;
1230 unsigned long rc;
1231 hdd_adapter_t *goAdapter;
1232 uint16_t current_freq;
Naveen Rawat5b34c952016-02-05 17:08:25 -08001233 uint8_t home_ch = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001234
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301235 ENTER();
1236
Anurag Chouhan6d760662016-02-20 16:05:43 +05301237 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 hddLog(LOGE, FL("Command not allowed in FTM mode"));
1239 return -EINVAL;
1240 }
1241
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301242 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001243 TRACE_CODE_HDD_ACTION, pAdapter->sessionId,
1244 pAdapter->device_mode));
1245 status = wlan_hdd_validate_context(pHddCtx);
1246
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301247 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249
Naveen Rawat5b34c952016-02-05 17:08:25 -08001250 hddLog(LOG1, FL("Device_mode %s(%d) type: %d, wait: %d, offchan: %d, category: %d, actionId: %d"),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001251 hdd_device_mode_to_string(pAdapter->device_mode),
Naveen Rawat5b34c952016-02-05 17:08:25 -08001252 pAdapter->device_mode, type, wait, offchan,
1253 buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET +
1254 WLAN_HDD_PUBLIC_ACTION_FRAME_CATEGORY_OFFSET],
1255 buf[WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET +
1256 WLAN_HDD_PUBLIC_ACTION_FRAME_ACTION_OFFSET]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257
1258#ifdef WLAN_FEATURE_P2P_DEBUG
1259 if ((type == SIR_MAC_MGMT_FRAME) &&
1260 (subType == SIR_MAC_MGMT_ACTION) &&
1261 wlan_hdd_is_type_p2p_action(&buf
1262 [WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET])) {
1263 actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
1264 if (actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301265 hddLog(QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001266 "[P2P] unknown[%d] ---> OTA to " MAC_ADDRESS_STR,
1267 actionFrmType,
1268 MAC_ADDR_ARRAY(&buf
1269 [WLAN_HDD_80211_FRM_DA_OFFSET]));
1270 } else {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301271 hddLog(QDF_TRACE_LEVEL_ERROR, "[P2P] %s ---> OTA to "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272 MAC_ADDRESS_STR,
1273 p2p_action_frame_type[actionFrmType],
1274 MAC_ADDR_ARRAY(&buf
1275 [WLAN_HDD_80211_FRM_DA_OFFSET]));
1276 if ((actionFrmType == WLAN_HDD_PROV_DIS_REQ)
1277 && (global_p2p_connection_status == P2P_NOT_ACTIVE)) {
1278 global_p2p_connection_status = P2P_GO_NEG_PROCESS;
1279 hddLog(LOGE, "[P2P State]Inactive state to "
1280 "GO negotiation progress state");
1281 } else if ((actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
1282 (global_p2p_connection_status ==
1283 P2P_GO_NEG_PROCESS)) {
1284 global_p2p_connection_status =
1285 P2P_GO_NEG_COMPLETED;
1286 hddLog(LOGE,
1287 "[P2P State]GO nego progress to GO nego"
1288 " completed state");
1289 }
1290 }
1291 }
1292#endif
1293
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001294 noack = dont_wait_for_ack;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295
1296 /* If the wait is coming as 0 with off channel set */
1297 /* then set the wait to 200 ms */
1298 if (offchan && !wait) {
1299 wait = ACTION_FRAME_DEFAULT_WAIT;
1300 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
1301 if (cfgState->remain_on_chan_ctx) {
1302
Anurag Chouhan210db072016-02-22 18:42:15 +05301303 uint32_t current_time = qdf_mc_timer_get_system_time();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001304 int remaining_roc_time =
1305 ((int) cfgState->remain_on_chan_ctx->duration -
1306 (current_time - pAdapter->start_roc_ts));
1307
1308 if (remaining_roc_time > ACTION_FRAME_DEFAULT_WAIT)
1309 wait = remaining_roc_time;
1310 }
1311 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
1312 }
1313
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001314 if ((QDF_STA_MODE == pAdapter->device_mode) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001315 (type == SIR_MAC_MGMT_FRAME &&
1316 subType == SIR_MAC_MGMT_PROBE_RSP)) {
1317 /* Drop Probe response received
1318 * from supplicant in sta mode
1319 */
1320 goto err_rem_channel;
1321 }
1322
1323 /* Call sme API to send out a action frame. */
1324 /* OR can we send it directly through data path?? */
1325 /* After tx completion send tx status back. */
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001326 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
1327 (QDF_P2P_GO_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001328 ) {
1329 if (type == SIR_MAC_MGMT_FRAME) {
1330 if (subType == SIR_MAC_MGMT_PROBE_RSP) {
1331 /* Drop Probe response recieved from supplicant, as for GO and
1332 SAP PE itself sends probe response
1333 */
1334 goto err_rem_channel;
1335 } else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
1336 (subType == SIR_MAC_MGMT_DEAUTH)) {
1337 /* During EAP failure or P2P Group Remove supplicant
1338 * is sending del_station command to driver. From
1339 * del_station function, Driver will send deauth frame to
1340 * p2p client. No need to send disassoc frame from here.
1341 * so Drop the frame here and send tx indication back to
1342 * supplicant.
1343 */
1344 uint8_t dstMac[ETH_ALEN] = { 0 };
1345 memcpy(&dstMac,
1346 &buf[WLAN_HDD_80211_FRM_DA_OFFSET],
1347 ETH_ALEN);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301348 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001349 "%s: Deauth/Disassoc received for STA:"
1350 MAC_ADDRESS_STR, __func__,
1351 MAC_ADDR_ARRAY(dstMac));
1352 goto err_rem_channel;
1353 }
1354 }
1355 }
1356
1357 if (NULL != cfgState->buf) {
1358 if (!noack) {
1359 hddLog(LOGE,
1360 "(%s):Previous P2P Action frame packet pending",
1361 __func__);
1362 hdd_cleanup_actionframe(pAdapter->pHddCtx, pAdapter);
1363 } else {
1364 hddLog(LOGE,
1365 "(%s):Pending Action frame packet return EBUSY",
1366 __func__);
1367 return -EBUSY;
1368 }
1369 }
1370
1371 if (subType == SIR_MAC_MGMT_ACTION) {
1372 hddLog(LOG1, "Action frame tx request : %s",
1373 hdd_get_action_string(buf
1374 [WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET]));
1375 }
1376
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001377 if (pAdapter->device_mode == QDF_SAP_MODE) {
Naveen Rawat5b34c952016-02-05 17:08:25 -08001378 home_ch = pAdapter->sessionCtx.ap.operatingChannel;
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001379 } else if (pAdapter->device_mode == QDF_STA_MODE) {
Naveen Rawat5b34c952016-02-05 17:08:25 -08001380 home_ch =
1381 pAdapter->sessionCtx.station.conn_info.operationChannel;
1382 } else {
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001383 goAdapter = hdd_get_adapter(pAdapter->pHddCtx, QDF_P2P_GO_MODE);
Naveen Rawat5b34c952016-02-05 17:08:25 -08001384 if (goAdapter)
1385 home_ch = goAdapter->sessionCtx.ap.operatingChannel;
1386 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387
Archana Ramachandrandc7f2c92016-06-27 11:44:13 -07001388 if (chan &&
1389 (ieee80211_frequency_to_channel(chan->center_freq) ==
1390 home_ch)) {
Naveen Rawat5b34c952016-02-05 17:08:25 -08001391 /* if adapter is already on requested ch, no need for ROC */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001392 wait = 0;
Naveen Rawat5b34c952016-02-05 17:08:25 -08001393 hddLog(LOG1,
1394 FL("Adapter already on requested ch. No ROC needed"));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395 goto send_frame;
1396 }
1397
Archana Ramachandrandc7f2c92016-06-27 11:44:13 -07001398 if (offchan && wait && chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001399 int status;
1400 rem_on_channel_request_type_t req_type = OFF_CHANNEL_ACTION_TX;
1401 /* In case of P2P Client mode if we are already */
1402 /* on the same channel then send the frame directly */
1403
1404 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
1405 pRemainChanCtx = cfgState->remain_on_chan_ctx;
1406 if ((type == SIR_MAC_MGMT_FRAME) &&
1407 (subType == SIR_MAC_MGMT_ACTION) &&
1408 hdd_p2p_is_action_type_rsp(&buf
1409 [WLAN_HDD_PUBLIC_ACTION_FRAME_BODY_OFFSET])
1410 && cfgState->remain_on_chan_ctx
1411 && cfgState->current_freq == chan->center_freq) {
Anurag Chouhan210db072016-02-22 18:42:15 +05301412 if (QDF_TIMER_STATE_RUNNING ==
1413 qdf_mc_timer_get_current_state(&cfgState->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001414 remain_on_chan_ctx->
1415 hdd_remain_on_chan_timer)) {
Deepthi Gowri1f835212016-08-30 19:37:05 +05301416
1417 /* In the latest wpa_supplicant, the wait time
1418 * for go negotiation response is set to 100ms,
1419 * due to which, there could be a possibility
1420 * that, if the go negotaition confirmation
1421 * frame is not received within 100 msec, ROC
1422 * would be timeout and resulting in connection
1423 * failures as the device will not be on the
1424 * listen channel anymore to receive the conf
1425 * frame. Also wpa_supplicant has set the wait
1426 * to 50msec for go negotiation confirmation,
1427 * invitation response and prov discovery rsp
1428 * frames. So increase the wait time for all
1429 * these frames.
1430 */
1431 actionFrmType = buf
1432 [WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
1433 if (actionFrmType == WLAN_HDD_GO_NEG_RESP ||
1434 actionFrmType == WLAN_HDD_PROV_DIS_RESP)
1435 wait = wait + ACTION_FRAME_RSP_WAIT;
1436 else if (actionFrmType ==
1437 WLAN_HDD_GO_NEG_CNF ||
1438 actionFrmType ==
1439 WLAN_HDD_INVITATION_RESP)
1440 wait = wait + ACTION_FRAME_ACK_WAIT;
1441
1442 hddLog(LOG1, FL("Extending the wait time %d for actionFrmType=%d"),
1443 wait, actionFrmType);
1444
Anurag Chouhan210db072016-02-22 18:42:15 +05301445 qdf_mc_timer_stop(&cfgState->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 remain_on_chan_ctx->
1447 hdd_remain_on_chan_timer);
1448 status =
Anurag Chouhan210db072016-02-22 18:42:15 +05301449 qdf_mc_timer_start(&cfgState->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450 remain_on_chan_ctx->
1451 hdd_remain_on_chan_timer,
1452 wait);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301453 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 hddLog(LOGE,
1455 "%s: Remain on Channel timer start failed",
1456 __func__);
1457 }
1458 mutex_unlock(&cfgState->
1459 remain_on_chan_ctx_lock);
1460 goto send_frame;
1461 } else {
1462 if (pRemainChanCtx->
1463 hdd_remain_on_chan_cancel_in_progress ==
1464 true) {
1465 mutex_unlock(&cfgState->
1466 remain_on_chan_ctx_lock);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301467 hddLog(QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468 "action frame tx: waiting for completion of ROC ");
1469
1470 rc = wait_for_completion_timeout
1471 (&pAdapter->cancel_rem_on_chan_var,
1472 msecs_to_jiffies
1473 (WAIT_CANCEL_REM_CHAN));
1474 if (!rc) {
1475 hddLog(LOGE,
1476 "%s:wait on cancel_rem_on_chan_var timed out",
1477 __func__);
1478 }
1479
1480 } else
1481 mutex_unlock(&cfgState->
1482 remain_on_chan_ctx_lock);
1483 }
1484 } else
1485 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
1486
1487 if ((cfgState->remain_on_chan_ctx != NULL) &&
1488 (cfgState->current_freq == chan->center_freq)
1489 ) {
1490 hddLog(LOG1, "action frame: extending the wait time");
1491 extendedWait = (uint16_t) wait;
1492 goto send_frame;
1493 }
1494
1495 INIT_COMPLETION(pAdapter->offchannel_tx_event);
1496
1497 status = wlan_hdd_request_remain_on_channel(wiphy, dev, chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001498 wait, cookie,
1499 req_type);
1500 if (0 != status) {
1501 if ((-EBUSY == status) &&
1502 (cfgState->current_freq == chan->center_freq)) {
1503 goto send_frame;
1504 }
1505 goto err_rem_channel;
1506 }
1507 /* This will extend timer in LIM when sending Any action frame
1508 * It will cover remain on channel timer till next action frame
1509 * in rx direction.
1510 */
1511 extendedWait = (uint16_t) wait;
1512 /* Wait for driver to be ready on the requested channel */
1513 rc = wait_for_completion_timeout(&pAdapter->offchannel_tx_event,
1514 msecs_to_jiffies
1515 (WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
1516 if (!rc) {
1517 hddLog(LOGE, "wait on offchannel_tx_event timed out");
1518 goto err_rem_channel;
1519 }
1520 } else if (offchan) {
1521 /* Check before sending action frame
1522 whether we already remain on channel */
1523 if (NULL == cfgState->remain_on_chan_ctx) {
1524 goto err_rem_channel;
1525 }
1526 }
1527send_frame:
1528
1529 if (!noack) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301530 cfgState->buf = qdf_mem_malloc(len); /* buf; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001531 if (cfgState->buf == NULL)
1532 return -ENOMEM;
1533
1534 cfgState->len = len;
1535
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301536 qdf_mem_copy(cfgState->buf, buf, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001537
1538 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
1539
1540 if (cfgState->remain_on_chan_ctx) {
1541 cfgState->action_cookie =
1542 cfgState->remain_on_chan_ctx->cookie;
1543 *cookie = cfgState->action_cookie;
1544 } else {
1545 *cookie = (uintptr_t) cfgState->buf;
1546 cfgState->action_cookie = *cookie;
1547 }
1548
1549 mutex_unlock(&cfgState->remain_on_chan_ctx_lock);
1550 }
1551
1552 /*
1553 * Firmware needs channel information for action frames
1554 * which are not sent on the current operating channel of VDEV
1555 */
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001556 if ((QDF_P2P_DEVICE_MODE == pAdapter->device_mode) ||
1557 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) ||
1558 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 if (chan && (chan->center_freq != 0))
1560 current_freq = chan->center_freq;
1561 else
1562 current_freq = cfgState->current_freq;
1563 } else {
1564 current_freq = 0;
1565 }
1566
Jeff Johnson19caeb12015-12-10 12:29:44 -08001567 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1568
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001569 if ((QDF_STA_MODE == pAdapter->device_mode) ||
1570 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) ||
1571 (QDF_P2P_DEVICE_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001572 ) {
1573 uint8_t sessionId = pAdapter->sessionId;
1574
1575 if ((type == SIR_MAC_MGMT_FRAME) &&
1576 (subType == SIR_MAC_MGMT_ACTION) &&
1577 (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] ==
1578 WLAN_HDD_PUBLIC_ACTION_FRAME)) {
1579 actionFrmType =
1580 buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
1581 hddLog(LOG1, "Tx Action Frame %u", actionFrmType);
1582 if (actionFrmType == WLAN_HDD_PROV_DIS_REQ) {
1583 cfgState->actionFrmState =
1584 HDD_PD_REQ_ACK_PENDING;
1585 hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING",
1586 __func__);
1587 } else if (actionFrmType == WLAN_HDD_GO_NEG_REQ) {
1588 cfgState->actionFrmState =
1589 HDD_GO_NEG_REQ_ACK_PENDING;
1590 hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING",
1591 __func__);
1592 }
1593 }
1594
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301595 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 sme_send_action(WLAN_HDD_GET_HAL_CTX(pAdapter),
1597 sessionId, buf, len, extendedWait, noack,
1598 current_freq)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301599 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001600 "%s: sme_send_action returned fail", __func__);
1601 goto err;
1602 }
Krunal Sonifb84cbd2016-03-10 13:09:07 -08001603 } else if (QDF_SAP_MODE == pAdapter->device_mode ||
1604 QDF_P2P_GO_MODE == pAdapter->device_mode) {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301605 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001606 wlansap_send_action(WLAN_HDD_GET_SAP_CTX_PTR(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607 buf, len, 0, current_freq)) {
1608 hddLog(LOGE,
1609 FL("wlansap_send_action returned fail"));
1610 goto err;
1611 }
1612 }
1613
1614 return 0;
1615err:
1616 if (!noack) {
1617 hdd_send_action_cnf(pAdapter, false);
1618 }
1619 return 0;
1620err_rem_channel:
1621 *cookie = (uintptr_t) cfgState;
1622 cfg80211_mgmt_tx_status(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001623 pAdapter->dev->ieee80211_ptr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001624 *cookie, buf, len, false, GFP_KERNEL);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301625 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001626 return 0;
1627}
1628
1629#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1630int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
1631 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
Amar Singhal01098f72015-10-08 11:55:32 -07001632#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001633int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
1634 struct ieee80211_channel *chan, bool offchan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001635 unsigned int wait,
1636 const u8 *buf, size_t len, bool no_cck,
1637 bool dont_wait_for_ack, u64 *cookie)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001638#endif /* LINUX_VERSION_CODE */
1639{
1640 int ret;
1641
1642 cds_ssr_protect(__func__);
1643
1644#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
1645 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan,
1646 params->wait, params->buf, params->len,
1647 params->no_cck, params->dont_wait_for_ack,
1648 cookie);
Amar Singhal01098f72015-10-08 11:55:32 -07001649#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001650 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, chan, offchan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001651 wait, buf, len, no_cck,
1652 dont_wait_for_ack, cookie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001653#endif /* LINUX_VERSION_CODE */
1654 cds_ssr_unprotect(__func__);
1655
1656 return ret;
1657}
1658
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001659int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1660 struct wireless_dev *wdev,
1661 u64 cookie)
1662{
1663 return wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, wdev, cookie);
1664}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001665
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001666int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
1667 struct wireless_dev *wdev, u64 cookie)
1668{
1669 int ret;
1670
1671 cds_ssr_protect(__func__);
1672 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
1673 cds_ssr_unprotect(__func__);
1674
1675 return ret;
1676}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001677
1678void hdd_send_action_cnf(hdd_adapter_t *pAdapter, bool actionSendSuccess)
1679{
1680 hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
1681
1682 cfgState->actionFrmState = HDD_IDLE;
1683
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001684
1685 if (NULL == cfgState->buf) {
1686 return;
1687 }
1688
Gowri, Deepthi62da33e2016-09-02 16:01:26 +05301689 if (cfgState->is_go_neg_ack_received) {
1690
1691 cfgState->is_go_neg_ack_received = 0;
1692 /* Sometimes its possible that host may receive the ack for GO
1693 * negotiation req after sending go negotaition confirmation,
1694 * in such case drop the ack received for the go negotiation
1695 * request, so that supplicant waits for the confirmation ack
1696 * from firmware.
1697 */
1698 hdd_info("Drop the pending ack received in cfgState->actionFrmState %d",
1699 cfgState->actionFrmState);
1700 return;
1701 }
1702
1703 hdd_info("Send Action cnf, actionSendSuccess %d",
1704 actionSendSuccess);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001705 /*
1706 * buf is the same pointer it passed us to send. Since we are sending
1707 * it through control path, we use different buffers.
1708 * In case of mac80211, they just push it to the skb and pass the same
1709 * data while sending tx ack status.
1710 * */
1711 cfg80211_mgmt_tx_status(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001712 pAdapter->dev->ieee80211_ptr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001713 cfgState->action_cookie,
1714 cfgState->buf, cfgState->len,
1715 actionSendSuccess, GFP_KERNEL);
1716
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301717 qdf_mem_free(cfgState->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001718 cfgState->buf = NULL;
1719
1720 complete(&pAdapter->tx_action_cnf_event);
1721}
1722
1723/**
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05301724 * hdd_send_action_cnf_cb - action confirmation callback
1725 * @session_id: SME session ID
1726 * @tx_completed: ack status
1727 *
1728 * This function invokes hdd_sendActionCnf to update ack status to
1729 * supplicant.
1730 */
1731void hdd_send_action_cnf_cb(uint32_t session_id, bool tx_completed)
1732{
1733 hdd_context_t *hdd_ctx;
1734 hdd_adapter_t *adapter;
1735
1736 ENTER();
1737
1738 /* Get the HDD context.*/
1739 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1740 if (0 != wlan_hdd_validate_context(hdd_ctx))
1741 return;
1742
1743 adapter = hdd_get_adapter_by_sme_session_id(hdd_ctx, session_id);
1744 if (NULL == adapter) {
1745 hddLog(LOGE, FL("adapter not found"));
1746 return;
1747 }
1748
1749 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1750 hddLog(LOGE, FL("adapter has invalid magic"));
1751 return;
1752 }
1753
1754 hdd_send_action_cnf(adapter, tx_completed);
1755}
1756
1757/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001758 * hdd_set_p2p_noa
1759 *
1760 ***FUNCTION:
1761 * This function is called from hdd_hostapd_ioctl function when Driver
1762 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
1763 *
1764 ***LOGIC:
1765 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1766 *
1767 ***ASSUMPTIONS:
1768 *
1769 *
1770 ***NOTE:
1771 *
1772 * @param dev Pointer to net device structure
1773 * @param command Pointer to command
1774 *
1775 * @return Status
1776 */
1777
1778int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command)
1779{
1780 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1781 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
1782 tP2pPsConfig NoA;
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +05301783 int count, duration, interval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784 char *param;
1785 int ret;
1786
1787 param = strnchr(command, strlen(command), ' ');
1788 if (param == NULL) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301789 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001790 "%s: strnchr failed to find delimeter", __func__);
1791 return -EINVAL;
1792 }
1793 param++;
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +05301794 ret = sscanf(param, "%d %d %d", &count, &interval, &duration);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795 if (ret != 3) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301796 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001797 "%s: P2P_SET GO NoA: fail to read params, ret=%d",
1798 __func__, ret);
1799 return -EINVAL;
1800 }
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301801 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +05301802 "%s: P2P_SET GO NoA: count=%d interval=%d duration=%d",
1803 __func__, count, interval, duration);
1804 duration = MS_TO_TU_MUS(duration);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001805 /* PS Selection
1806 * Periodic NoA (2)
1807 * Single NOA (4)
1808 */
1809 NoA.opp_ps = 0;
1810 NoA.ctWindow = 0;
1811 if (count == 1) {
1812 NoA.duration = 0;
1813 NoA.single_noa_duration = duration;
1814 NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
1815 } else {
1816 NoA.duration = duration;
1817 NoA.single_noa_duration = 0;
1818 NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
1819 }
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +05301820 NoA.interval = MS_TO_TU_MUS(interval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001821 NoA.count = count;
1822 NoA.sessionid = pAdapter->sessionId;
1823
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301824 QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825 "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
1826 "interval %d count %d single noa duration %d "
1827 "PsSelection %x", __func__, NoA.opp_ps,
1828 NoA.ctWindow, NoA.duration, NoA.interval,
1829 NoA.count, NoA.single_noa_duration, NoA.psSelection);
1830
1831 sme_p2p_set_ps(hHal, &NoA);
1832 return 0;
1833}
1834
1835/**
1836 * hdd_set_p2p_opps
1837 *
1838 ***FUNCTION:
1839 * This function is called from hdd_hostapd_ioctl function when Driver
1840 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
1841 *
1842 ***LOGIC:
1843 * Fill NoA Struct According to P2P Power save Option and Pass it to SME layer
1844 *
1845 ***ASSUMPTIONS:
1846 *
1847 *
1848 ***NOTE:
1849 *
1850 * @param dev Pointer to net device structure
1851 * @param command Pointer to command
1852 *
1853 * @return Status
1854 */
1855
1856int hdd_set_p2p_opps(struct net_device *dev, uint8_t *command)
1857{
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301858 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1859 tHalHandle handle = WLAN_HDD_GET_HAL_CTX(adapter);
1860 tP2pPsConfig noa;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001861 char *param;
1862 int legacy_ps, opp_ps, ctwindow;
1863 int ret;
1864
1865 param = strnchr(command, strlen(command), ' ');
1866 if (param == NULL) {
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301867 hdd_err("strnchr failed to find delimiter");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 return -EINVAL;
1869 }
1870 param++;
1871 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
1872 if (ret != 3) {
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301873 hdd_err("P2P_SET GO PS: fail to read params, ret=%d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874 return -EINVAL;
1875 }
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301876
1877 if ((opp_ps != -1) && (opp_ps != 0) && (opp_ps != 1)) {
1878 hdd_err("Invalid opp_ps value:%d", opp_ps);
1879 return -EINVAL;
1880 }
1881
1882 /* P2P spec: 3.3.2 Power Management and discovery:
1883 * CTWindow should be at least 10 TU.
1884 * P2P spec: Table 27 - CTWindow and OppPS Parameters field format:
1885 * CTWindow and OppPS Parameters together is 8 bits.
1886 * CTWindow uses 7 bits (0-6, Bit 7 is for OppPS)
1887 * 0 indicates that there shall be no CTWindow
1888 */
1889 if ((ctwindow != -1) && (ctwindow != 0) &&
1890 (!((ctwindow >= 10) && (ctwindow <= 127)))) {
1891 hdd_err("Invalid CT window value:%d", ctwindow);
1892 return -EINVAL;
1893 }
1894
1895 hdd_info("P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
1896 legacy_ps, opp_ps, ctwindow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897
1898 /* PS Selection
1899 * Opportunistic Power Save (1)
1900 */
1901
1902 /* From wpa_cli user need to use separate command to set ctWindow and Opps
1903 * When user want to set ctWindow during that time other parameters
1904 * values are coming from wpa_supplicant as -1.
1905 * Example : User want to set ctWindow with 30 then wpa_cli command :
1906 * P2P_SET ctwindow 30
1907 * Command Received at hdd_hostapd_ioctl is as below:
1908 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301909 *
1910 * e.g., 1: P2P_SET_PS 1 1 30
1911 * Driver sets the Opps and CTwindow as 30 and send it to FW.
1912 * e.g., 2: P2P_SET_PS 1 -1 15
1913 * Driver caches the CTwindow value but not send the command to FW.
1914 * e.g., 3: P2P_SET_PS 1 1 -1
1915 * Driver sends the command to FW with Opps enabled and CT window as
1916 * 15 (last cached CTWindow value).
1917 * (or) : P2P_SET_PS 1 1 20
1918 * Driver sends the command to FW with opps enabled and CT window
1919 * as 20.
1920 *
1921 * legacy_ps param remains unused until required in the future.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001922 */
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301923 if (ctwindow != -1)
1924 adapter->ctw = ctwindow;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001925
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301926 /* Send command to FW when OppPS is either enabled(1)/disbaled(0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 if (opp_ps != -1) {
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301928 adapter->ops = opp_ps;
1929 noa.opp_ps = adapter->ops;
1930 noa.ctWindow = adapter->ctw;
1931 noa.duration = 0;
1932 noa.single_noa_duration = 0;
1933 noa.interval = 0;
1934 noa.count = 0;
1935 noa.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
1936 noa.sessionid = adapter->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001937
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301938 hdd_debug("P2P_PS_ATTR: oppPS %d ctWindow %d duration %d interval %d count %d single noa duration %d PsSelection %x",
1939 noa.opp_ps, noa.ctWindow,
1940 noa.duration, noa.interval, noa.count,
1941 noa.single_noa_duration,
1942 noa.psSelection);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001943
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301944 sme_p2p_set_ps(handle, &noa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001945 }
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +05301946
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001947 return 0;
1948}
1949
1950int hdd_set_p2p_ps(struct net_device *dev, void *msgData)
1951{
1952 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1953 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301954 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955 tP2pPsConfig NoA;
1956 p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;
1957
1958 NoA.opp_ps = pappNoA->opp_ps;
1959 NoA.ctWindow = pappNoA->ctWindow;
1960 NoA.duration = pappNoA->duration;
1961 NoA.interval = pappNoA->interval;
1962 NoA.count = pappNoA->count;
1963 NoA.single_noa_duration = pappNoA->single_noa_duration;
1964 NoA.psSelection = pappNoA->psSelection;
1965 NoA.sessionid = pAdapter->sessionId;
1966
1967 sme_p2p_set_ps(hHal, &NoA);
1968 return status;
1969}
1970
1971static uint8_t wlan_hdd_get_session_type(enum nl80211_iftype type)
1972{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 switch (type) {
1974 case NL80211_IFTYPE_AP:
Dustin Brown0a1da142016-09-13 13:31:52 -07001975 return QDF_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001976 case NL80211_IFTYPE_P2P_GO:
Dustin Brown0a1da142016-09-13 13:31:52 -07001977 return QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 case NL80211_IFTYPE_P2P_CLIENT:
Dustin Brown0a1da142016-09-13 13:31:52 -07001979 return QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001980 case NL80211_IFTYPE_STATION:
Dustin Brown0a1da142016-09-13 13:31:52 -07001981 return QDF_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001982 default:
Dustin Brown0a1da142016-09-13 13:31:52 -07001983 return QDF_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001984 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985}
1986
Ryan Hsu07495ea2016-01-21 15:25:39 -08001987/**
1988 * __wlan_hdd_add_virtual_intf() - Add virtual interface
1989 * @wiphy: wiphy pointer
1990 * @name: User-visible name of the interface
1991 * @name_assign_type: the name of assign type of the netdev
1992 * @nl80211_iftype: (virtual) interface types
1993 * @flags: moniter configuraiton flags (not used)
1994 * @vif_params: virtual interface parameters (not used)
1995 *
Arun Khandavallic67110c2016-08-18 16:18:51 +05301996 * Return: the pointer of wireless dev, otherwise ERR_PTR.
Ryan Hsu07495ea2016-01-21 15:25:39 -08001997 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
1999 const char *name,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002000 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002001 enum nl80211_iftype type,
2002 u32 *flags,
2003 struct vif_params *params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002004{
2005 hdd_context_t *pHddCtx = (hdd_context_t *) wiphy_priv(wiphy);
2006 hdd_adapter_t *pAdapter = NULL;
2007 hdd_scaninfo_t *scan_info = NULL;
2008 int ret;
Peng Xu45486ea2015-11-12 16:37:44 -08002009 uint8_t session_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010
2011 ENTER();
2012
Anurag Chouhan6d760662016-02-20 16:05:43 +05302013 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014 hddLog(LOGE, FL("Command not allowed in FTM mode"));
2015 return ERR_PTR(-EINVAL);
2016 }
2017
2018 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302019 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002020 return ERR_PTR(ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002021
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302022 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002023 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
2024 /*
Krunal Sonifb84cbd2016-03-10 13:09:07 -08002025 * Allow addition multiple interfaces for QDF_P2P_GO_MODE,
2026 * QDF_SAP_MODE, QDF_P2P_CLIENT_MODE and QDF_STA_MODE
Peng Xu45486ea2015-11-12 16:37:44 -08002027 * session type.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 */
Peng Xu45486ea2015-11-12 16:37:44 -08002029 session_type = wlan_hdd_get_session_type(type);
Dustin Brown0a1da142016-09-13 13:31:52 -07002030 if (hdd_get_adapter(pHddCtx, session_type) != NULL
Krunal Sonifb84cbd2016-03-10 13:09:07 -08002031 && QDF_SAP_MODE != session_type
2032 && QDF_P2P_GO_MODE != session_type
Krunal Sonifb84cbd2016-03-10 13:09:07 -08002033 && QDF_P2P_CLIENT_MODE != session_type
2034 && QDF_STA_MODE != session_type) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002035 hddLog(LOGE,
2036 "%s: Interface type %d already exists. "
2037 "Two interfaces of same type are not supported currently.",
2038 __func__, type);
2039 return ERR_PTR(-EINVAL);
2040 }
2041
2042 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
2043
Krunal Sonifb84cbd2016-03-10 13:09:07 -08002044 pAdapter = hdd_get_adapter(pHddCtx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 if (pAdapter != NULL) {
2046 scan_info = &pAdapter->scan_info;
2047 if (scan_info->mScanPending) {
2048 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
2049 eCSR_SCAN_ABORT_DEFAULT);
2050 hddLog(LOG1,
2051 FL("Abort Scan while adding virtual interface"));
2052 }
2053 }
2054
2055 pAdapter = NULL;
2056 if (pHddCtx->config->isP2pDeviceAddrAdministrated &&
2057 ((NL80211_IFTYPE_P2P_GO == type) ||
2058 (NL80211_IFTYPE_P2P_CLIENT == type))) {
2059 /*
2060 * Generate the P2P Interface Address. this address must be
2061 * different from the P2P Device Address.
2062 */
Anurag Chouhan6d760662016-02-20 16:05:43 +05302063 struct qdf_mac_addr p2pDeviceAddress =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002064 pHddCtx->p2pDeviceAddress;
2065 p2pDeviceAddress.bytes[4] ^= 0x80;
2066 pAdapter = hdd_open_adapter(pHddCtx,
Dustin Brown0a1da142016-09-13 13:31:52 -07002067 session_type,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002068 name, p2pDeviceAddress.bytes,
2069 name_assign_type,
2070 true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002071 } else {
Ryan Hsu07495ea2016-01-21 15:25:39 -08002072 pAdapter = hdd_open_adapter(pHddCtx,
Dustin Brown0a1da142016-09-13 13:31:52 -07002073 session_type,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002074 name,
2075 wlan_hdd_get_intf_addr(pHddCtx),
2076 name_assign_type,
2077 true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002078 }
2079
2080 if (NULL == pAdapter) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302081 hddLog(QDF_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002082 __func__);
2083 return ERR_PTR(-ENOSPC);
2084 }
Nirav Shahbd36b062016-07-18 11:12:59 +05302085
Arun Khandavalli99286452016-08-22 12:13:41 +05302086 /*
2087 * Add interface can be requested from the upper layer at any time
2088 * check the statemachine for modules state and if they are closed
2089 * open the modules.
2090 */
2091 ret = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
2092 if (ret)
2093 return ERR_PTR(ret);
2094
Arun Khandavalli812d0692016-09-01 19:11:56 +05302095 /*
2096 * Once the support for session creation/deletion from
2097 * hdd_hostapd_open/hdd_host_stop is in place.
2098 * The support for starting adapter from here can be removed.
2099 */
2100 if (NL80211_IFTYPE_AP == type || (NL80211_IFTYPE_P2P_GO == type)) {
Arun Khandavallic67110c2016-08-18 16:18:51 +05302101 ret = hdd_start_adapter(pAdapter);
2102 if (ret) {
2103 hdd_err("Failed to start %s", name);
2104 return ERR_PTR(-EINVAL);
2105 }
2106 }
2107
Nirav Shahbd36b062016-07-18 11:12:59 +05302108 if (pHddCtx->rps)
2109 hdd_send_rps_ind(pAdapter);
2110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002111 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002112 return pAdapter->dev->ieee80211_ptr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002113}
2114
Ryan Hsu07495ea2016-01-21 15:25:39 -08002115#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || defined(WITH_BACKPORTS)
2116/**
2117 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
2118 * @wiphy: wiphy pointer
2119 * @name: User-visible name of the interface
2120 * @name_assign_type: the name of assign type of the netdev
2121 * @nl80211_iftype: (virtual) interface types
2122 * @flags: monitor mode configuration flags (not used)
2123 * @vif_params: virtual interface parameters (not used)
2124 *
Arun Khandavallic67110c2016-08-18 16:18:51 +05302125 * Return: the pointer of wireless dev, otherwise ERR_PTR.
Ryan Hsu07495ea2016-01-21 15:25:39 -08002126 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002127struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2128 const char *name,
Ryan Hsu07495ea2016-01-21 15:25:39 -08002129 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002130 enum nl80211_iftype type,
2131 u32 *flags,
2132 struct vif_params *params)
2133{
2134 struct wireless_dev *wdev;
2135
2136 cds_ssr_protect(__func__);
Ryan Hsu07495ea2016-01-21 15:25:39 -08002137 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
2138 type, flags, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 cds_ssr_unprotect(__func__);
2140 return wdev;
Ryan Hsu07495ea2016-01-21 15:25:39 -08002141
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002142}
Ryan Hsu07495ea2016-01-21 15:25:39 -08002143#else
2144/**
2145 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
2146 * @wiphy: wiphy pointer
2147 * @name: User-visible name of the interface
2148 * @nl80211_iftype: (virtual) interface types
2149 * @flags: monitor mode configuration flags (not used)
2150 * @vif_params: virtual interface parameters (not used)
2151 *
Arun Khandavallic67110c2016-08-18 16:18:51 +05302152 * Return: the pointer of wireless dev, otherwise ERR_PTR.
Ryan Hsu07495ea2016-01-21 15:25:39 -08002153 */
2154struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
2155 const char *name,
2156 enum nl80211_iftype type,
2157 u32 *flags,
2158 struct vif_params *params)
2159{
2160 struct wireless_dev *wdev;
2161 unsigned char name_assign_type = 0;
2162
2163 cds_ssr_protect(__func__);
2164 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
2165 type, flags, params);
2166 cds_ssr_unprotect(__func__);
2167 return wdev;
2168
2169}
2170#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002172int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002173{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 struct net_device *dev = wdev->netdev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002175 hdd_context_t *pHddCtx = (hdd_context_t *) wiphy_priv(wiphy);
2176 hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2177 int status;
2178 ENTER();
2179
Anurag Chouhan6d760662016-02-20 16:05:43 +05302180 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002181 hddLog(LOGE, FL("Command not allowed in FTM mode"));
2182 return -EINVAL;
2183 }
2184
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302185 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002186 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
2187 pVirtAdapter->sessionId, pVirtAdapter->device_mode));
2188 hddLog(LOG1, FL("Device_mode %s(%d)"),
2189 hdd_device_mode_to_string(pVirtAdapter->device_mode),
2190 pVirtAdapter->device_mode);
2191
2192 status = wlan_hdd_validate_context(pHddCtx);
2193
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302194 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002196
Arun Khandavalli99286452016-08-22 12:13:41 +05302197 /*
2198 * check state machine state and kickstart modules if they are closed.
2199 */
2200 status = hdd_wlan_start_modules(pHddCtx, pVirtAdapter, false);
2201 if (status)
2202 return status;
2203
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002204 wlan_hdd_release_intf_addr(pHddCtx,
2205 pVirtAdapter->macAddressCurrent.bytes);
2206
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05302207 if ((pVirtAdapter->device_mode == QDF_SAP_MODE) &&
2208 wlan_sap_is_pre_cac_active(pHddCtx->hHal)) {
2209 hdd_clean_up_pre_cac_interface(pHddCtx);
2210 }
2211
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002212 hdd_stop_adapter(pHddCtx, pVirtAdapter, true);
2213 hdd_close_adapter(pHddCtx, pVirtAdapter, true);
2214 EXIT();
2215 return 0;
2216}
2217
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002218int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219{
2220 int ret;
2221
2222 cds_ssr_protect(__func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002223 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002224 cds_ssr_unprotect(__func__);
2225
2226 return ret;
2227}
2228
Sandeep Puligillad180c5e2016-06-06 12:06:21 -07002229#ifdef WLAN_FEATURE_P2P_DEBUG
2230/*
2231 * wlan_hdd_p2p_action_debug() - Log P2P state and update global status
2232 * @actionFrmType: action frame type
2233 * @macFrom: peer mac address
2234 *
2235 * return: void
2236 */
2237static void wlan_hdd_p2p_action_debug(tActionFrmType actionFrmType,
2238 uint8_t *macFrom)
2239{
2240 if (actionFrmType >= MAX_P2P_ACTION_FRAME_TYPE) {
2241 hdd_err("[P2P] unknown[%d] <--- OTA from " MAC_ADDRESS_STR,
2242 actionFrmType, MAC_ADDR_ARRAY(macFrom));
2243 } else {
2244 hdd_err("[P2P] %s <--- OTA from " MAC_ADDRESS_STR,
2245 p2p_action_frame_type[actionFrmType],
2246 MAC_ADDR_ARRAY(macFrom));
2247 if ((actionFrmType == WLAN_HDD_PROV_DIS_REQ)
2248 && (global_p2p_connection_status == P2P_NOT_ACTIVE)) {
2249 global_p2p_connection_status = P2P_GO_NEG_PROCESS;
2250 hdd_err("[P2P State]Inactive state to GO negotiation progress state");
2251 } else
2252 if ((actionFrmType == WLAN_HDD_GO_NEG_CNF)
2253 && (global_p2p_connection_status == P2P_GO_NEG_PROCESS)) {
2254 global_p2p_connection_status = P2P_GO_NEG_COMPLETED;
2255 hdd_err("[P2P State]GO negotiation progress to GO negotiation completed state");
2256 } else
2257 if ((actionFrmType == WLAN_HDD_INVITATION_REQ)
2258 && (global_p2p_connection_status == P2P_NOT_ACTIVE)) {
2259 global_p2p_connection_status = P2P_GO_NEG_COMPLETED;
2260 hdd_err("[P2P State]Inactive state to GO negotiation completed state Autonomous GO formation");
2261 }
2262 }
2263}
2264#else
2265/*
2266 * wlan_hdd_p2p_action_debug() - dummy
2267 * @actionFrmType: action frame type
2268 * @macFrom: peer mac address
2269 *
2270 * return: void
2271 */
2272static void wlan_hdd_p2p_action_debug(tActionFrmType actionFrmType,
2273 uint8_t *macFrom)
2274{
2275
2276}
2277#endif
2278
Abhishek Singh7996eb72015-12-30 17:24:02 +05302279void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002280 uint32_t nFrameLength,
2281 uint8_t *pbFrames,
2282 uint8_t frameType, uint32_t rxChan, int8_t rxRssi)
2283{
2284 uint16_t freq;
2285 uint16_t extend_time;
2286 uint8_t type = 0;
2287 uint8_t subType = 0;
2288 tActionFrmType actionFrmType;
2289 hdd_cfg80211_state_t *cfgState = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302290 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002291 hdd_remain_on_chan_ctx_t *pRemainChanCtx = NULL;
2292 hdd_context_t *pHddCtx;
2293
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05302294 hddLog(QDF_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002295 __func__, frameType, nFrameLength);
2296
2297 if (NULL == pAdapter) {
2298 hddLog(LOGE, FL("pAdapter is NULL"));
2299 return;
2300 }
2301 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2302
2303 if (0 == nFrameLength) {
2304 hddLog(LOGE, FL("Frame Length is Invalid ZERO"));
2305 return;
2306 }
2307
2308 if (NULL == pbFrames) {
2309 hddLog(LOGE, FL("pbFrames is NULL"));
2310 return;
2311 }
2312
2313 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
2314 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
2315
2316 /* Get pAdapter from Destination mac address of the frame */
2317 if ((type == SIR_MAC_MGMT_FRAME) && (subType != SIR_MAC_MGMT_PROBE_REQ)) {
2318 pAdapter =
2319 hdd_get_adapter_by_macaddr(WLAN_HDD_GET_CTX(pAdapter),
2320 &pbFrames
2321 [WLAN_HDD_80211_FRM_DA_OFFSET]);
2322 if (NULL == pAdapter) {
2323 /*
2324 * Under assumtion that we don't receive any action
2325 * frame with BCST as destination,
2326 * we are dropping action frame
2327 */
2328 hddLog(LOGP,
2329 "pAdapter for action frame is NULL Macaddr = "
2330 MAC_ADDRESS_STR,
2331 MAC_ADDR_ARRAY(&pbFrames
2332 [WLAN_HDD_80211_FRM_DA_OFFSET]));
2333 hddLog(LOGP,
2334 FL("Frame Type = %d Frame Length = %d subType = %d"),
2335 frameType, nFrameLength, subType);
2336 return;
2337 }
2338 }
2339
2340 if (NULL == pAdapter->dev) {
2341 hddLog(LOGE, FL("pAdapter->dev is NULL"));
2342 return;
2343 }
2344
2345 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) {
2346 hddLog(LOGE, FL("pAdapter has invalid magic"));
2347 return;
2348 }
2349
2350 /* Channel indicated may be wrong. TODO */
2351 /* Indicate an action frame. */
2352 if (rxChan <= MAX_NO_OF_2_4_CHANNELS)
2353 freq = ieee80211_channel_to_frequency(rxChan,
2354 IEEE80211_BAND_2GHZ);
2355 else
2356 freq = ieee80211_channel_to_frequency(rxChan,
2357 IEEE80211_BAND_5GHZ);
2358
2359 cfgState = WLAN_HDD_GET_CFG_STATE_PTR(pAdapter);
2360
2361 if ((type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_ACTION)) {
2362 if (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] ==
2363 WLAN_HDD_PUBLIC_ACTION_FRAME) {
2364 /* Public action frame */
2365 if ((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1]
2366 == SIR_MAC_ACTION_VENDOR_SPECIFIC) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302367 !qdf_mem_cmp(&pbFrames
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002368 [WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET
2369 + 2], SIR_MAC_P2P_OUI,
2370 SIR_MAC_P2P_OUI_SIZE)) {
2371 /* P2P action frames */
Sandeep Puligillad180c5e2016-06-06 12:06:21 -07002372 uint8_t *macFrom = &pbFrames
Abhishek Singh437606a2016-04-27 13:51:49 +05302373 [WLAN_HDD_80211_PEER_ADDR_OFFSET];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002374 actionFrmType =
2375 pbFrames
2376 [WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
2377 hddLog(LOG1, "Rx Action Frame %u",
2378 actionFrmType);
Sandeep Puligillad180c5e2016-06-06 12:06:21 -07002379
2380 wlan_hdd_p2p_action_debug(actionFrmType,
2381 macFrom);
2382
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002383 mutex_lock(&cfgState->remain_on_chan_ctx_lock);
2384 pRemainChanCtx = cfgState->remain_on_chan_ctx;
2385 if (pRemainChanCtx != NULL) {
2386 if (actionFrmType == WLAN_HDD_GO_NEG_REQ
2387 || actionFrmType ==
2388 WLAN_HDD_GO_NEG_RESP
2389 || actionFrmType ==
2390 WLAN_HDD_INVITATION_REQ
2391 || actionFrmType ==
2392 WLAN_HDD_DEV_DIS_REQ
2393 || actionFrmType ==
2394 WLAN_HDD_PROV_DIS_REQ) {
2395 hddLog(LOG1,
2396 "Extend RoC timer on reception of Action Frame");
2397
2398 if ((actionFrmType ==
2399 WLAN_HDD_GO_NEG_REQ)
2400 || (actionFrmType ==
2401 WLAN_HDD_GO_NEG_RESP))
2402 extend_time =
2403 2 *
2404 ACTION_FRAME_DEFAULT_WAIT;
2405 else
2406 extend_time =
2407 ACTION_FRAME_DEFAULT_WAIT;
2408
2409 if (completion_done
2410 (&pAdapter->
2411 rem_on_chan_ready_event)) {
Anurag Chouhan210db072016-02-22 18:42:15 +05302412 if (QDF_TIMER_STATE_RUNNING == qdf_mc_timer_get_current_state(&pRemainChanCtx->hdd_remain_on_chan_timer)) {
2413 qdf_mc_timer_stop
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002414 (&pRemainChanCtx->
2415 hdd_remain_on_chan_timer);
2416 status =
Anurag Chouhan210db072016-02-22 18:42:15 +05302417 qdf_mc_timer_start
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418 (&pRemainChanCtx->
2419 hdd_remain_on_chan_timer,
2420 extend_time);
2421 if (status !=
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302422 QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423 hddLog
2424 (LOGE,
2425 "%s: Remain on Channel timer start failed",
2426 __func__);
2427 }
2428 } else {
2429 hddLog(LOG1,
2430 "%s: Rcvd action frame after timer expired",
2431 __func__);
2432 }
2433 } else {
2434 /* Buffer Packet */
2435 if (pRemainChanCtx->
2436 action_pkt_buff.
2437 frame_length == 0) {
2438 pRemainChanCtx->
2439 action_pkt_buff.
2440 frame_length
2441 =
2442 nFrameLength;
2443 pRemainChanCtx->
2444 action_pkt_buff.
2445 freq = freq;
2446 pRemainChanCtx->
2447 action_pkt_buff.
2448 frame_ptr =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302449 qdf_mem_malloc
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002450 (nFrameLength);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302451 qdf_mem_copy
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452 (pRemainChanCtx->
2453 action_pkt_buff.
2454 frame_ptr,
2455 pbFrames,
2456 nFrameLength);
2457 hddLog(LOGE,
2458 "%s:"
2459 "Action Pkt Cached successfully !!!",
2460 __func__);
2461 } else {
2462 hddLog(LOGE,
2463 "%s:"
2464 "Frames are pending. dropping frame !!!",
2465 __func__);
2466 }
2467 mutex_unlock(&cfgState->
2468 remain_on_chan_ctx_lock);
2469 return;
2470 }
2471 }
2472 }
2473 mutex_unlock(&cfgState->
2474 remain_on_chan_ctx_lock);
2475
2476 if (((actionFrmType == WLAN_HDD_PROV_DIS_RESP)
2477 && (cfgState->actionFrmState ==
2478 HDD_PD_REQ_ACK_PENDING))
2479 || ((actionFrmType == WLAN_HDD_GO_NEG_RESP)
2480 && (cfgState->actionFrmState ==
2481 HDD_GO_NEG_REQ_ACK_PENDING))) {
2482 hddLog(LOG1,
2483 "%s: ACK_PENDING and But received RESP for Action frame ",
2484 __func__);
Gowri, Deepthi62da33e2016-09-02 16:01:26 +05302485 cfgState->is_go_neg_ack_received = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002486 hdd_send_action_cnf(pAdapter, true);
2487 }
2488 }
2489#ifdef FEATURE_WLAN_TDLS
2490 else if (pbFrames
2491 [WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1] ==
2492 WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP) {
Abhishek Singh437606a2016-04-27 13:51:49 +05302493 u8 *mac = &pbFrames
2494 [WLAN_HDD_80211_PEER_ADDR_OFFSET];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002495
2496 hddLog(LOG1,
2497 "[TDLS] TDLS Discovery Response,"
2498 MAC_ADDRESS_STR " RSSI[%d] <--- OTA",
2499 MAC_ADDR_ARRAY(mac), rxRssi);
2500
2501 wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi);
2502 wlan_hdd_tdls_recv_discovery_resp(pAdapter,
2503 mac);
Abhishek Singh437606a2016-04-27 13:51:49 +05302504 cds_tdls_tx_rx_mgmt_event(SIR_MAC_ACTION_TDLS,
2505 SIR_MAC_ACTION_RX, SIR_MAC_MGMT_ACTION,
2506 WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP,
2507 &pbFrames[WLAN_HDD_80211_PEER_ADDR_OFFSET]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002508 }
2509#endif
2510 }
2511
2512 if (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] ==
2513 WLAN_HDD_TDLS_ACTION_FRAME) {
2514 actionFrmType =
2515 pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1];
2516 if (actionFrmType >= MAX_TDLS_ACTION_FRAME_TYPE) {
2517 hddLog(LOG1,
2518 "[TDLS] unknown[%d] <--- OTA",
2519 actionFrmType);
2520 } else {
2521 hddLog(LOG1,
2522 "[TDLS] %s <--- OTA",
2523 tdls_action_frame_type[actionFrmType]);
2524 }
Abhishek Singh437606a2016-04-27 13:51:49 +05302525 cds_tdls_tx_rx_mgmt_event(SIR_MAC_ACTION_TDLS,
2526 SIR_MAC_ACTION_RX, SIR_MAC_MGMT_ACTION,
2527 actionFrmType,
2528 &pbFrames[WLAN_HDD_80211_PEER_ADDR_OFFSET]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002529 }
2530
2531 if ((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] ==
2532 WLAN_HDD_QOS_ACTION_FRAME)
2533 && (pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1] ==
2534 WLAN_HDD_QOS_MAP_CONFIGURE)) {
2535 sme_update_dsc_pto_up_mapping(pHddCtx->hHal,
2536 pAdapter->hddWmmDscpToUpMap,
2537 pAdapter->sessionId);
2538 }
2539 }
2540 /* Indicate Frame Over Normal Interface */
Arun Khandavallib2f6c262016-08-18 19:07:19 +05302541 hddLog(LOG1, FL("Indicate Frame over NL80211 sessionid : %d, idx :%d"),
2542 pAdapter->sessionId, pAdapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002543
2544#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
2545 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames,
2546 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED);
2547#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
2548 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0, pbFrames,
2549 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED,
2550 GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002551#else
Amar Singhal01098f72015-10-08 11:55:32 -07002552 cfg80211_rx_mgmt(pAdapter->dev->ieee80211_ptr, freq, 0,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 pbFrames, nFrameLength, GFP_ATOMIC);
2554#endif /* LINUX_VERSION_CODE */
2555}
2556