blob: 9762cdb302aa4a09beec8a04affe60a1f2c71cab [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Dustin Browndb2a8be2017-12-20 11:49:56 -08002 * Copyright (c) 2012-2018 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"
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080054#include "wlan_policy_mgr_api.h"
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053055#include "cds_utils.h"
Wu Gao9a704f42017-03-10 18:42:11 +080056#include "wlan_p2p_public_struct.h"
57#include "wlan_p2p_ucfg_api.h"
58#include "wlan_cfg80211_p2p.h"
Wu Gao9a704f42017-03-10 18:42:11 +080059
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +053060/* Ms to Time Unit Micro Sec */
61#define MS_TO_TU_MUS(x) ((x) * 1024)
Archana Ramachandran1e6b9262016-09-30 15:15:10 -070062#define MAX_MUS_VAL (INT_MAX / 1024)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080063
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080064#ifdef WLAN_FEATURE_P2P_DEBUG
65#define MAX_P2P_ACTION_FRAME_TYPE 9
66const char *p2p_action_frame_type[] = { "GO Negotiation Request",
67 "GO Negotiation Response",
68 "GO Negotiation Confirmation",
69 "P2P Invitation Request",
70 "P2P Invitation Response",
71 "Device Discoverability Request",
72 "Device Discoverability Response",
73 "Provision Discovery Request",
74 "Provision Discovery Response"};
75
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080076#endif
77#define MAX_TDLS_ACTION_FRAME_TYPE 11
78const char *tdls_action_frame_type[] = { "TDLS Setup Request",
79 "TDLS Setup Response",
80 "TDLS Setup Confirm",
81 "TDLS Teardown",
82 "TDLS Peer Traffic Indication",
83 "TDLS Channel Switch Request",
84 "TDLS Channel Switch Response",
85 "TDLS Peer PSM Request",
86 "TDLS Peer PSM Response",
87 "TDLS Peer Traffic Response",
88 "TDLS Discovery Request"};
89
Jeff Johnson19b66e82017-10-02 13:25:56 -070090void wlan_hdd_cancel_existing_remain_on_channel(struct hdd_adapter *adapter)
Wu Gao8a45ede2017-04-06 20:04:06 +080091{
92 QDF_STATUS status;
93
Jeff Johnson19b66e82017-10-02 13:25:56 -070094 if (!adapter) {
Wu Gao8a45ede2017-04-06 20:04:06 +080095 hdd_err("null adapter");
96 return;
97 }
98
Jeff Johnson19b66e82017-10-02 13:25:56 -070099 status = ucfg_p2p_cleanup_roc(adapter->hdd_vdev);
Wu Gao8a45ede2017-04-06 20:04:06 +0800100 hdd_debug("status:%d", status);
101}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800102
Jeff Johnson19b66e82017-10-02 13:25:56 -0700103int wlan_hdd_check_remain_on_channel(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800104{
Wu Gao02bd75b2017-10-13 18:34:02 +0800105 if (QDF_P2P_GO_MODE != adapter->device_mode)
106 wlan_hdd_cancel_existing_remain_on_channel(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800107
Wu Gao02bd75b2017-10-13 18:34:02 +0800108 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800109}
110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111/* Clean up RoC context at hdd_stop_adapter*/
Jeff Johnson19b66e82017-10-02 13:25:56 -0700112void wlan_hdd_cleanup_remain_on_channel_ctx(struct hdd_adapter *adapter)
Wu Gao8a45ede2017-04-06 20:04:06 +0800113{
114 QDF_STATUS status;
115
Jeff Johnson19b66e82017-10-02 13:25:56 -0700116 if (!adapter) {
Wu Gao8a45ede2017-04-06 20:04:06 +0800117 hdd_err("null adapter");
118 return;
119 }
120
Jeff Johnson19b66e82017-10-02 13:25:56 -0700121 status = ucfg_p2p_cleanup_roc(adapter->hdd_vdev);
Wu Gao8a45ede2017-04-06 20:04:06 +0800122 hdd_debug("status:%d", status);
123}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800124
Wu Gao9a704f42017-03-10 18:42:11 +0800125static int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
126 struct wireless_dev *wdev,
127 struct ieee80211_channel *chan,
128 unsigned int duration,
129 u64 *cookie)
130{
131 struct net_device *dev = wdev->netdev;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700132 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson18767622017-08-28 11:46:50 -0700133 struct hdd_context *hdd_ctx;
Wu Gao9a704f42017-03-10 18:42:11 +0800134 QDF_STATUS status;
135 int ret;
136
137 ENTER();
138
Jeff Johnson19b66e82017-10-02 13:25:56 -0700139 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Wu Gao9a704f42017-03-10 18:42:11 +0800140 ret = wlan_hdd_validate_context(hdd_ctx);
141 if (0 != ret)
142 return ret;
143
144 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
145 hdd_err("Command not allowed in FTM mode");
146 return -EINVAL;
147 }
148
Jeff Johnson1b780e42017-10-31 14:11:45 -0700149 if (wlan_hdd_validate_session_id(adapter->session_id)) {
150 hdd_err("invalid session id: %d", adapter->session_id);
Wu Gao9a704f42017-03-10 18:42:11 +0800151 return -EINVAL;
152 }
153
Jeff Johnson19b66e82017-10-02 13:25:56 -0700154 status = wlan_cfg80211_roc(adapter->hdd_vdev, chan,
Wu Gao9a704f42017-03-10 18:42:11 +0800155 duration, cookie);
Wu Gao02bd75b2017-10-13 18:34:02 +0800156 hdd_debug("remain on channel request, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +0800157
158 return qdf_status_to_os_return(status);
159}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160
161int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800162 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163 struct ieee80211_channel *chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800164 unsigned int duration, u64 *cookie)
165{
166 int ret;
167
168 cds_ssr_protect(__func__);
169 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170 wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800171 chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800172 duration, cookie);
173 cds_ssr_unprotect(__func__);
174
175 return ret;
176}
177
Wu Gao9a704f42017-03-10 18:42:11 +0800178static int
179__wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
180 struct wireless_dev *wdev,
181 u64 cookie)
182{
183 QDF_STATUS status;
184 struct net_device *dev = wdev->netdev;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700185 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao9a704f42017-03-10 18:42:11 +0800186
187 ENTER();
188
189 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
190 hdd_err("Command not allowed in FTM mode");
191 return -EINVAL;
192 }
193
Jeff Johnson1b780e42017-10-31 14:11:45 -0700194 if (wlan_hdd_validate_session_id(adapter->session_id)) {
195 hdd_err("invalid session id: %d", adapter->session_id);
Wu Gao9a704f42017-03-10 18:42:11 +0800196 return -EINVAL;
197 }
198
Jeff Johnson19b66e82017-10-02 13:25:56 -0700199 status = wlan_cfg80211_cancel_roc(adapter->hdd_vdev, cookie);
Wu Gao02bd75b2017-10-13 18:34:02 +0800200 hdd_debug("cancel remain on channel, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +0800201
202 return 0;
203}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204
205int wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800206 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207 u64 cookie)
208{
209 int ret;
210
211 cds_ssr_protect(__func__);
212 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213 wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800214 cookie);
215 cds_ssr_unprotect(__func__);
216
217 return ret;
218}
219
Wu Gao9a704f42017-03-10 18:42:11 +0800220static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
221 struct ieee80211_channel *chan, bool offchan,
222 unsigned int wait,
223 const u8 *buf, size_t len, bool no_cck,
224 bool dont_wait_for_ack, u64 *cookie)
225{
226 QDF_STATUS status;
227 struct net_device *dev = wdev->netdev;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700228 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Padma, Santhosh Kumar22c462c2018-01-16 17:56:44 +0530229 uint8_t type;
230 uint8_t sub_type;
231 QDF_STATUS qdf_status;
Wu Gao9a704f42017-03-10 18:42:11 +0800232
233 ENTER();
234
235 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
236 hdd_err("Command not allowed in FTM mode");
237 return -EINVAL;
238 }
239
Jeff Johnson1b780e42017-10-31 14:11:45 -0700240 if (wlan_hdd_validate_session_id(adapter->session_id)) {
241 hdd_err("invalid session id: %d", adapter->session_id);
Wu Gao9a704f42017-03-10 18:42:11 +0800242 return -EINVAL;
243 }
244
Padma, Santhosh Kumar22c462c2018-01-16 17:56:44 +0530245 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
246 sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
247
248 /* When frame to be transmitted is auth mgmt, then trigger
249 * sme_send_mgmt_tx to send auth frame without need for policy manager.
250 * Where as wlan_cfg80211_mgmt_tx requires roc and requires approval
251 * from policy manager.
252 */
253 if ((adapter->device_mode == QDF_STA_MODE) &&
254 (type == SIR_MAC_MGMT_FRAME &&
255 sub_type == SIR_MAC_MGMT_AUTH)) {
256 qdf_status = sme_send_mgmt_tx(WLAN_HDD_GET_HAL_CTX(adapter),
257 adapter->session_id, buf, len);
258
259 if (QDF_IS_STATUS_SUCCESS(qdf_status))
260 return 0;
261 else
262 return -EINVAL;
263 }
264
Jeff Johnson19b66e82017-10-02 13:25:56 -0700265 status = wlan_cfg80211_mgmt_tx(adapter->hdd_vdev, chan,
Wu Gao9a704f42017-03-10 18:42:11 +0800266 offchan, wait, buf, len, no_cck,
267 dont_wait_for_ack, cookie);
Wu Gao02bd75b2017-10-13 18:34:02 +0800268 hdd_debug("mgmt tx, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +0800269
270 return 0;
271}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800272
273#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
274int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
275 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
Amar Singhal01098f72015-10-08 11:55:32 -0700276#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800277int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
278 struct ieee80211_channel *chan, bool offchan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800279 unsigned int wait,
280 const u8 *buf, size_t len, bool no_cck,
281 bool dont_wait_for_ack, u64 *cookie)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800282#endif /* LINUX_VERSION_CODE */
283{
284 int ret;
285
286 cds_ssr_protect(__func__);
287
288#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
289 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan,
290 params->wait, params->buf, params->len,
291 params->no_cck, params->dont_wait_for_ack,
292 cookie);
Amar Singhal01098f72015-10-08 11:55:32 -0700293#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800294 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, chan, offchan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295 wait, buf, len, no_cck,
296 dont_wait_for_ack, cookie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297#endif /* LINUX_VERSION_CODE */
298 cds_ssr_unprotect(__func__);
299
300 return ret;
301}
302
Wu Gao9a704f42017-03-10 18:42:11 +0800303static int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
304 struct wireless_dev *wdev,
305 u64 cookie)
306{
307 QDF_STATUS status;
308 struct net_device *dev = wdev->netdev;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700309 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao9a704f42017-03-10 18:42:11 +0800310
311 ENTER();
312
313 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
314 hdd_err("Command not allowed in FTM mode");
315 return -EINVAL;
316 }
317
Jeff Johnson1b780e42017-10-31 14:11:45 -0700318 if (wlan_hdd_validate_session_id(adapter->session_id)) {
319 hdd_err("invalid session id: %d", adapter->session_id);
Wu Gao9a704f42017-03-10 18:42:11 +0800320 return -EINVAL;
321 }
322
Jeff Johnson19b66e82017-10-02 13:25:56 -0700323 status = wlan_cfg80211_mgmt_tx_cancel(adapter->hdd_vdev,
Wu Gao9a704f42017-03-10 18:42:11 +0800324 cookie);
Wu Gao02bd75b2017-10-13 18:34:02 +0800325 hdd_debug("cancel mgmt tx, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +0800326
327 return 0;
328}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800329
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800330int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
331 struct wireless_dev *wdev, u64 cookie)
332{
333 int ret;
334
335 cds_ssr_protect(__func__);
336 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
337 cds_ssr_unprotect(__func__);
338
339 return ret;
340}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800341
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +0530342/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343 * hdd_set_p2p_noa
344 *
345 ***FUNCTION:
346 * This function is called from hdd_hostapd_ioctl function when Driver
347 * get P2P_SET_NOA comand from wpa_supplicant using private ioctl
348 *
349 ***LOGIC:
Wu Gao02bd75b2017-10-13 18:34:02 +0800350 * Fill noa Struct According to P2P Power save Option and Pass it to SME layer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351 *
352 ***ASSUMPTIONS:
353 *
354 *
355 ***NOTE:
356 *
357 * @param dev Pointer to net device structure
358 * @param command Pointer to command
359 *
360 * @return Status
361 */
362
363int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command)
364{
Jeff Johnson19b66e82017-10-02 13:25:56 -0700365 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao02bd75b2017-10-13 18:34:02 +0800366 struct p2p_ps_config noa = {0};
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +0530367 int count, duration, interval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800368 char *param;
369 int ret;
370
371 param = strnchr(command, strlen(command), ' ');
372 if (param == NULL) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700373 hdd_err("strnchr failed to find delimeter");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800374 return -EINVAL;
375 }
376 param++;
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +0530377 ret = sscanf(param, "%d %d %d", &count, &interval, &duration);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378 if (ret != 3) {
Wu Gao02bd75b2017-10-13 18:34:02 +0800379 hdd_err("P2P_SET GO noa: fail to read params, ret=%d",
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700380 ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800381 return -EINVAL;
382 }
Archana Ramachandran1e6b9262016-09-30 15:15:10 -0700383 if (count < 0 || interval < 0 || duration < 0 ||
384 interval > MAX_MUS_VAL || duration > MAX_MUS_VAL) {
385 hdd_err("Invalid NOA parameters");
386 return -EINVAL;
387 }
Wu Gao02bd75b2017-10-13 18:34:02 +0800388 hdd_debug("P2P_SET GO noa: count=%d interval=%d duration=%d",
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700389 count, interval, duration);
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +0530390 duration = MS_TO_TU_MUS(duration);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391 /* PS Selection
Wu Gao02bd75b2017-10-13 18:34:02 +0800392 * Periodic noa (2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393 * Single NOA (4)
394 */
Wu Gao02bd75b2017-10-13 18:34:02 +0800395 noa.opp_ps = 0;
396 noa.ct_window = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800397 if (count == 1) {
Wu Gao02bd75b2017-10-13 18:34:02 +0800398 noa.duration = 0;
399 noa.single_noa_duration = duration;
400 noa.ps_selection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800401 } else {
Wu Gao02bd75b2017-10-13 18:34:02 +0800402 noa.duration = duration;
403 noa.single_noa_duration = 0;
404 noa.ps_selection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800405 }
Wu Gao02bd75b2017-10-13 18:34:02 +0800406 noa.interval = MS_TO_TU_MUS(interval);
407 noa.count = count;
Jeff Johnson1b780e42017-10-31 14:11:45 -0700408 noa.vdev_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800409
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800410 hdd_debug("P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800411 "interval %d count %d single noa duration %d "
Wu Gao02bd75b2017-10-13 18:34:02 +0800412 "PsSelection %x", noa.opp_ps,
413 noa.ct_window, noa.duration, noa.interval,
414 noa.count, noa.single_noa_duration, noa.ps_selection);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800415
Wu Gao02bd75b2017-10-13 18:34:02 +0800416 return wlan_hdd_set_power_save(adapter, &noa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800417}
418
419/**
420 * hdd_set_p2p_opps
421 *
422 ***FUNCTION:
423 * This function is called from hdd_hostapd_ioctl function when Driver
424 * get P2P_SET_PS comand from wpa_supplicant using private ioctl
425 *
426 ***LOGIC:
Wu Gao02bd75b2017-10-13 18:34:02 +0800427 * Fill noa Struct According to P2P Power save Option and Pass it to SME layer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800428 *
429 ***ASSUMPTIONS:
430 *
431 *
432 ***NOTE:
433 *
434 * @param dev Pointer to net device structure
435 * @param command Pointer to command
436 *
437 * @return Status
438 */
439
440int hdd_set_p2p_opps(struct net_device *dev, uint8_t *command)
441{
Jeff Johnsonfbb54522017-08-29 14:25:27 -0700442 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao02bd75b2017-10-13 18:34:02 +0800443 struct p2p_ps_config noa = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800444 char *param;
445 int legacy_ps, opp_ps, ctwindow;
446 int ret;
447
448 param = strnchr(command, strlen(command), ' ');
449 if (param == NULL) {
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530450 hdd_err("strnchr failed to find delimiter");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800451 return -EINVAL;
452 }
453 param++;
454 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
455 if (ret != 3) {
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530456 hdd_err("P2P_SET GO PS: fail to read params, ret=%d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800457 return -EINVAL;
458 }
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530459
460 if ((opp_ps != -1) && (opp_ps != 0) && (opp_ps != 1)) {
461 hdd_err("Invalid opp_ps value:%d", opp_ps);
462 return -EINVAL;
463 }
464
465 /* P2P spec: 3.3.2 Power Management and discovery:
466 * CTWindow should be at least 10 TU.
467 * P2P spec: Table 27 - CTWindow and OppPS Parameters field format:
468 * CTWindow and OppPS Parameters together is 8 bits.
469 * CTWindow uses 7 bits (0-6, Bit 7 is for OppPS)
470 * 0 indicates that there shall be no CTWindow
471 */
472 if ((ctwindow != -1) && (ctwindow != 0) &&
473 (!((ctwindow >= 10) && (ctwindow <= 127)))) {
474 hdd_err("Invalid CT window value:%d", ctwindow);
475 return -EINVAL;
476 }
477
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800478 hdd_debug("P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530479 legacy_ps, opp_ps, ctwindow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800480
481 /* PS Selection
482 * Opportunistic Power Save (1)
483 */
484
Srinivas Girigowdaef327802017-03-24 23:13:20 -0700485 /* From wpa_cli user need to use separate command to set ctWindow and
486 * Opps when user want to set ctWindow during that time other parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800487 * values are coming from wpa_supplicant as -1.
488 * Example : User want to set ctWindow with 30 then wpa_cli command :
489 * P2P_SET ctwindow 30
490 * Command Received at hdd_hostapd_ioctl is as below:
491 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530492 *
493 * e.g., 1: P2P_SET_PS 1 1 30
494 * Driver sets the Opps and CTwindow as 30 and send it to FW.
495 * e.g., 2: P2P_SET_PS 1 -1 15
496 * Driver caches the CTwindow value but not send the command to FW.
497 * e.g., 3: P2P_SET_PS 1 1 -1
498 * Driver sends the command to FW with Opps enabled and CT window as
499 * 15 (last cached CTWindow value).
500 * (or) : P2P_SET_PS 1 1 20
501 * Driver sends the command to FW with opps enabled and CT window
502 * as 20.
503 *
504 * legacy_ps param remains unused until required in the future.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505 */
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530506 if (ctwindow != -1)
507 adapter->ctw = ctwindow;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530509 /* Send command to FW when OppPS is either enabled(1)/disbaled(0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800510 if (opp_ps != -1) {
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530511 adapter->ops = opp_ps;
512 noa.opp_ps = adapter->ops;
Wu Gao02bd75b2017-10-13 18:34:02 +0800513 noa.ct_window = adapter->ctw;
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530514 noa.duration = 0;
515 noa.single_noa_duration = 0;
516 noa.interval = 0;
517 noa.count = 0;
Wu Gao02bd75b2017-10-13 18:34:02 +0800518 noa.ps_selection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
Jeff Johnson1b780e42017-10-31 14:11:45 -0700519 noa.vdev_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530521 hdd_debug("P2P_PS_ATTR: oppPS %d ctWindow %d duration %d interval %d count %d single noa duration %d PsSelection %x",
Wu Gao02bd75b2017-10-13 18:34:02 +0800522 noa.opp_ps, noa.ct_window,
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530523 noa.duration, noa.interval, noa.count,
524 noa.single_noa_duration,
Wu Gao02bd75b2017-10-13 18:34:02 +0800525 noa.ps_selection);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800526
Wu Gao9a704f42017-03-10 18:42:11 +0800527 wlan_hdd_set_power_save(adapter, &noa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 }
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530529
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800530 return 0;
531}
532
533int hdd_set_p2p_ps(struct net_device *dev, void *msgData)
534{
Jeff Johnson19b66e82017-10-02 13:25:56 -0700535 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao02bd75b2017-10-13 18:34:02 +0800536 struct p2p_ps_config noa = {0};
537 struct p2p_app_set_ps *pappnoa = (struct p2p_app_set_ps *) msgData;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538
Wu Gao02bd75b2017-10-13 18:34:02 +0800539 noa.opp_ps = pappnoa->opp_ps;
540 noa.ct_window = pappnoa->ctWindow;
541 noa.duration = pappnoa->duration;
542 noa.interval = pappnoa->interval;
543 noa.count = pappnoa->count;
544 noa.single_noa_duration = pappnoa->single_noa_duration;
545 noa.ps_selection = pappnoa->psSelection;
Jeff Johnson1b780e42017-10-31 14:11:45 -0700546 noa.vdev_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800547
Wu Gao02bd75b2017-10-13 18:34:02 +0800548 return wlan_hdd_set_power_save(adapter, &noa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549}
550
551static uint8_t wlan_hdd_get_session_type(enum nl80211_iftype type)
552{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 switch (type) {
554 case NL80211_IFTYPE_AP:
Dustin Brown0a1da142016-09-13 13:31:52 -0700555 return QDF_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800556 case NL80211_IFTYPE_P2P_GO:
Dustin Brown0a1da142016-09-13 13:31:52 -0700557 return QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558 case NL80211_IFTYPE_P2P_CLIENT:
Dustin Brown0a1da142016-09-13 13:31:52 -0700559 return QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800560 case NL80211_IFTYPE_STATION:
Dustin Brown0a1da142016-09-13 13:31:52 -0700561 return QDF_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562 default:
Dustin Brown0a1da142016-09-13 13:31:52 -0700563 return QDF_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800564 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800565}
566
Ryan Hsu07495ea2016-01-21 15:25:39 -0800567/**
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530568 * wlan_hdd_allow_sap_add() - check to add new sap interface
569 * @hdd_ctx: pointer to hdd context
570 * @name: name of the new interface
571 * @sap_dev: output pointer to hold existing interface
572 *
573 * Return: If able to add interface return true else false
574 */
575static bool
576wlan_hdd_allow_sap_add(struct hdd_context *hdd_ctx, const char *name,
577 struct wireless_dev **sap_dev)
578{
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530579 struct hdd_adapter *adapter;
580
581 *sap_dev = NULL;
Dustin Brown920397d2017-12-13 16:27:50 -0800582
583 hdd_for_each_adapter(hdd_ctx, adapter) {
584 if (adapter->device_mode == QDF_SAP_MODE &&
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530585 test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags) &&
586 !strncmp(adapter->dev->name, name, IFNAMSIZ)) {
587 struct hdd_beacon_data *beacon =
588 adapter->session.ap.beacon;
589
590 hdd_debug("iface already registered");
591 if (beacon) {
592 adapter->session.ap.beacon = NULL;
593 qdf_mem_free(beacon);
594 }
595 if (adapter->dev && adapter->dev->ieee80211_ptr) {
596 *sap_dev = adapter->dev->ieee80211_ptr;
597 return false;
598 }
599
600 hdd_err("ieee80211_ptr points to NULL");
601 return false;
602 }
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530603 }
604
605 return true;
606}
607
608/**
Ryan Hsu07495ea2016-01-21 15:25:39 -0800609 * __wlan_hdd_add_virtual_intf() - Add virtual interface
610 * @wiphy: wiphy pointer
611 * @name: User-visible name of the interface
612 * @name_assign_type: the name of assign type of the netdev
613 * @nl80211_iftype: (virtual) interface types
614 * @flags: moniter configuraiton flags (not used)
615 * @vif_params: virtual interface parameters (not used)
616 *
Arun Khandavallic67110c2016-08-18 16:18:51 +0530617 * Return: the pointer of wireless dev, otherwise ERR_PTR.
Ryan Hsu07495ea2016-01-21 15:25:39 -0800618 */
Jeff Johnsond2291042016-10-05 16:18:50 -0700619static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
621 const char *name,
Ryan Hsu07495ea2016-01-21 15:25:39 -0800622 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623 enum nl80211_iftype type,
624 u32 *flags,
625 struct vif_params *params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800626{
Jeff Johnson7c794a12017-09-03 09:20:55 -0700627 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
Jeff Johnson19b66e82017-10-02 13:25:56 -0700628 struct hdd_adapter *adapter = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629 int ret;
Peng Xu45486ea2015-11-12 16:37:44 -0800630 uint8_t session_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800631
632 ENTER();
633
Anurag Chouhan6d760662016-02-20 16:05:43 +0530634 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700635 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800636 return ERR_PTR(-EINVAL);
637 }
638
Jeff Johnson7c794a12017-09-03 09:20:55 -0700639 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530640 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641 return ERR_PTR(ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800642
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530643 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800644 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
645 /*
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800646 * Allow addition multiple interfaces for QDF_P2P_GO_MODE,
647 * QDF_SAP_MODE, QDF_P2P_CLIENT_MODE and QDF_STA_MODE
Peng Xu45486ea2015-11-12 16:37:44 -0800648 * session type.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800649 */
Peng Xu45486ea2015-11-12 16:37:44 -0800650 session_type = wlan_hdd_get_session_type(type);
Jeff Johnson7c794a12017-09-03 09:20:55 -0700651 if (hdd_get_adapter(hdd_ctx, session_type) != NULL
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800652 && QDF_SAP_MODE != session_type
653 && QDF_P2P_GO_MODE != session_type
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800654 && QDF_P2P_CLIENT_MODE != session_type
655 && QDF_STA_MODE != session_type) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700656 hdd_err("Interface type %d already exists. Two interfaces of same type are not supported currently.",
657 type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 return ERR_PTR(-EINVAL);
659 }
660
Jeff Johnson19b66e82017-10-02 13:25:56 -0700661 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
662 if ((adapter != NULL) &&
Jeff Johnson1b780e42017-10-31 14:11:45 -0700663 !(wlan_hdd_validate_session_id(adapter->session_id))) {
Sandeep Puligilla5f86d992017-10-29 14:58:53 -0700664 if (ucfg_scan_get_vdev_status(adapter->hdd_vdev) !=
665 SCAN_NOT_IN_PROGRESS) {
Jeff Johnson7c794a12017-09-03 09:20:55 -0700666 wlan_abort_scan(hdd_ctx->hdd_pdev, INVAL_PDEV_ID,
Jeff Johnson1b780e42017-10-31 14:11:45 -0700667 adapter->session_id, INVALID_SCAN_ID, false);
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800668 hdd_debug("Abort Scan while adding virtual interface");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800669 }
670 }
671
Hanumanth Reddy Pothula74a97d42017-11-20 21:43:54 +0530672 if (session_type == QDF_SAP_MODE) {
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530673 struct wireless_dev *sap_dev;
674 bool allow_add_sap = wlan_hdd_allow_sap_add(hdd_ctx, name,
675 &sap_dev);
676 if (!allow_add_sap) {
677 if (sap_dev)
678 return sap_dev;
Hanumanth Reddy Pothula74a97d42017-11-20 21:43:54 +0530679
Hanumanth Reddy Pothula74a97d42017-11-20 21:43:54 +0530680 return ERR_PTR(-EINVAL);
681 }
682 }
683
Jeff Johnson19b66e82017-10-02 13:25:56 -0700684 adapter = NULL;
Jeff Johnson7c794a12017-09-03 09:20:55 -0700685 if (hdd_ctx->config->isP2pDeviceAddrAdministrated &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 ((NL80211_IFTYPE_P2P_GO == type) ||
687 (NL80211_IFTYPE_P2P_CLIENT == type))) {
688 /*
689 * Generate the P2P Interface Address. this address must be
690 * different from the P2P Device Address.
691 */
Jeff Johnsonacbdb1c2017-11-02 20:42:02 -0700692 struct qdf_mac_addr p2p_device_address =
693 hdd_ctx->p2p_device_address;
694 p2p_device_address.bytes[4] ^= 0x80;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700695 adapter = hdd_open_adapter(hdd_ctx,
Dustin Brown0a1da142016-09-13 13:31:52 -0700696 session_type,
Jeff Johnsonacbdb1c2017-11-02 20:42:02 -0700697 name, p2p_device_address.bytes,
Ryan Hsu07495ea2016-01-21 15:25:39 -0800698 name_assign_type,
699 true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 } else {
Jeff Johnson19b66e82017-10-02 13:25:56 -0700701 adapter = hdd_open_adapter(hdd_ctx,
Dustin Brown0a1da142016-09-13 13:31:52 -0700702 session_type,
Ryan Hsu07495ea2016-01-21 15:25:39 -0800703 name,
Jeff Johnson7c794a12017-09-03 09:20:55 -0700704 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -0800705 name_assign_type,
706 true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707 }
708
Jeff Johnson19b66e82017-10-02 13:25:56 -0700709 if (NULL == adapter) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700710 hdd_err("hdd_open_adapter failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 return ERR_PTR(-ENOSPC);
712 }
Nirav Shahbd36b062016-07-18 11:12:59 +0530713
Arun Khandavalli99286452016-08-22 12:13:41 +0530714 /*
715 * Add interface can be requested from the upper layer at any time
716 * check the statemachine for modules state and if they are closed
717 * open the modules.
718 */
Jeff Johnson19b66e82017-10-02 13:25:56 -0700719 ret = hdd_wlan_start_modules(hdd_ctx, adapter, false);
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530720 if (ret) {
721 hdd_err("Failed to start the wlan_modules");
722 goto close_adapter;
723 }
Arun Khandavalli99286452016-08-22 12:13:41 +0530724
Arun Khandavalli812d0692016-09-01 19:11:56 +0530725 /*
726 * Once the support for session creation/deletion from
727 * hdd_hostapd_open/hdd_host_stop is in place.
728 * The support for starting adapter from here can be removed.
729 */
730 if (NL80211_IFTYPE_AP == type || (NL80211_IFTYPE_P2P_GO == type)) {
Jeff Johnson19b66e82017-10-02 13:25:56 -0700731 ret = hdd_start_adapter(adapter);
Arun Khandavallic67110c2016-08-18 16:18:51 +0530732 if (ret) {
733 hdd_err("Failed to start %s", name);
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530734 goto stop_modules;
Arun Khandavallic67110c2016-08-18 16:18:51 +0530735 }
736 }
737
Jeff Johnson7c794a12017-09-03 09:20:55 -0700738 if (hdd_ctx->rps)
Jeff Johnson19b66e82017-10-02 13:25:56 -0700739 hdd_send_rps_ind(adapter);
Nirav Shahbd36b062016-07-18 11:12:59 +0530740
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800741 EXIT();
Jeff Johnson19b66e82017-10-02 13:25:56 -0700742 return adapter->dev->ieee80211_ptr;
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530743
744stop_modules:
745 /*
746 * Find if any iface is up. If there is not iface which is up
747 * start the timer to close the modules
748 */
Jeff Johnson7c794a12017-09-03 09:20:55 -0700749 if (hdd_check_for_opened_interfaces(hdd_ctx)) {
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800750 hdd_debug("Closing all modules from the add_virt_iface");
Dustin Brown6f427922017-09-19 12:19:00 -0700751 qdf_sched_delayed_work(&hdd_ctx->iface_idle_work,
752 hdd_ctx->config->iface_change_wait_time);
Mukul Sharma07bd8752017-10-10 16:58:14 +0530753 hdd_prevent_suspend_timeout(
754 hdd_ctx->config->iface_change_wait_time,
755 WIFI_POWER_EVENT_WAKELOCK_IFACE_CHANGE_TIMER);
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530756 } else
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800757 hdd_debug("Other interfaces are still up dont close modules!");
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530758
759close_adapter:
Jeff Johnson19b66e82017-10-02 13:25:56 -0700760 hdd_close_adapter(hdd_ctx, adapter, true);
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530761
762 return ERR_PTR(-EINVAL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800763}
764
Dustin Brown9ed30a52017-08-16 13:59:38 -0700765#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
766struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
767 const char *name,
768 unsigned char name_assign_type,
769 enum nl80211_iftype type,
770 struct vif_params *params)
771{
772 struct wireless_dev *wdev;
773
774 cds_ssr_protect(__func__);
775 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
776 type, &params->flags, params);
777 cds_ssr_unprotect(__func__);
778
779 return wdev;
780}
781#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || defined(WITH_BACKPORTS)
Ryan Hsu07495ea2016-01-21 15:25:39 -0800782/**
783 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
784 * @wiphy: wiphy pointer
785 * @name: User-visible name of the interface
786 * @name_assign_type: the name of assign type of the netdev
787 * @nl80211_iftype: (virtual) interface types
788 * @flags: monitor mode configuration flags (not used)
789 * @vif_params: virtual interface parameters (not used)
790 *
Arun Khandavallic67110c2016-08-18 16:18:51 +0530791 * Return: the pointer of wireless dev, otherwise ERR_PTR.
Ryan Hsu07495ea2016-01-21 15:25:39 -0800792 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
794 const char *name,
Ryan Hsu07495ea2016-01-21 15:25:39 -0800795 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800796 enum nl80211_iftype type,
797 u32 *flags,
798 struct vif_params *params)
799{
800 struct wireless_dev *wdev;
801
802 cds_ssr_protect(__func__);
Ryan Hsu07495ea2016-01-21 15:25:39 -0800803 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
804 type, flags, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800805 cds_ssr_unprotect(__func__);
806 return wdev;
Ryan Hsu07495ea2016-01-21 15:25:39 -0800807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800808}
Ryan Hsu07495ea2016-01-21 15:25:39 -0800809#else
810/**
811 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
812 * @wiphy: wiphy pointer
813 * @name: User-visible name of the interface
814 * @nl80211_iftype: (virtual) interface types
815 * @flags: monitor mode configuration flags (not used)
816 * @vif_params: virtual interface parameters (not used)
817 *
Arun Khandavallic67110c2016-08-18 16:18:51 +0530818 * Return: the pointer of wireless dev, otherwise ERR_PTR.
Ryan Hsu07495ea2016-01-21 15:25:39 -0800819 */
820struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
821 const char *name,
822 enum nl80211_iftype type,
823 u32 *flags,
824 struct vif_params *params)
825{
826 struct wireless_dev *wdev;
827 unsigned char name_assign_type = 0;
828
829 cds_ssr_protect(__func__);
830 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
831 type, flags, params);
832 cds_ssr_unprotect(__func__);
833 return wdev;
834
835}
836#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800839{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800840 struct net_device *dev = wdev->netdev;
Jeff Johnson7c794a12017-09-03 09:20:55 -0700841 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
Jeff Johnsonfbb54522017-08-29 14:25:27 -0700842 struct hdd_adapter *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800843 int status;
Srinivas Girigowdaef327802017-03-24 23:13:20 -0700844
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800845 ENTER();
846
Anurag Chouhan6d760662016-02-20 16:05:43 +0530847 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700848 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800849 return -EINVAL;
850 }
851
Hanumanth Reddy Pothula74a97d42017-11-20 21:43:54 +0530852 /*
853 * Clear SOFTAP_INIT_DONE flag to mark SAP unload, so that we do
854 * not restart SAP after SSR as SAP is already stopped from user space.
855 */
856 clear_bit(SOFTAP_INIT_DONE, &pVirtAdapter->event_flags);
857
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530858 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
Jeff Johnson1b780e42017-10-31 14:11:45 -0700860 pVirtAdapter->session_id, pVirtAdapter->device_mode));
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800861 hdd_debug("Device_mode %s(%d)",
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700862 hdd_device_mode_to_string(pVirtAdapter->device_mode),
863 pVirtAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800864
Jeff Johnson7c794a12017-09-03 09:20:55 -0700865 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800866
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530867 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800868 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800869
Mukul Sharma24699bd2017-04-03 19:50:44 +0530870 /* check state machine state and kickstart modules if they are closed */
Jeff Johnson7c794a12017-09-03 09:20:55 -0700871 status = hdd_wlan_start_modules(hdd_ctx, pVirtAdapter, false);
Arun Khandavalli99286452016-08-22 12:13:41 +0530872 if (status)
873 return status;
874
Mukul Sharma24699bd2017-04-03 19:50:44 +0530875 if (pVirtAdapter->device_mode == QDF_SAP_MODE &&
Jeff Johnson7c794a12017-09-03 09:20:55 -0700876 wlan_sap_is_pre_cac_active(hdd_ctx->hHal)) {
877 hdd_clean_up_pre_cac_interface(hdd_ctx);
Mukul Sharma24699bd2017-04-03 19:50:44 +0530878 } else {
Jeff Johnson7c794a12017-09-03 09:20:55 -0700879 wlan_hdd_release_intf_addr(hdd_ctx,
Jeff Johnson1e851a12017-10-28 14:36:12 -0700880 pVirtAdapter->mac_addr.bytes);
Dustin Browndb2a8be2017-12-20 11:49:56 -0800881 hdd_stop_adapter(hdd_ctx, pVirtAdapter);
Krunal Sonic68ee302017-11-14 20:33:32 -0800882 hdd_deinit_adapter(hdd_ctx, pVirtAdapter, true);
Jeff Johnson7c794a12017-09-03 09:20:55 -0700883 hdd_close_adapter(hdd_ctx, pVirtAdapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +0530884 }
885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800886 EXIT();
Mukul Sharma24699bd2017-04-03 19:50:44 +0530887
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800888 return 0;
889}
890
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800891int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800892{
893 int ret;
894
895 cds_ssr_protect(__func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800896 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800897 cds_ssr_unprotect(__func__);
898
899 return ret;
900}
901
Jeff Johnson19b66e82017-10-02 13:25:56 -0700902void __hdd_indicate_mgmt_frame(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800903 uint32_t nFrameLength,
904 uint8_t *pbFrames,
905 uint8_t frameType, uint32_t rxChan, int8_t rxRssi)
906{
907 uint16_t freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800908 uint8_t type = 0;
909 uint8_t subType = 0;
Jeff Johnson7c794a12017-09-03 09:20:55 -0700910 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800911
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800912 hdd_debug("Frame Type = %d Frame Length = %d",
Samuel Ahn065e6492016-09-30 22:48:09 +0530913 frameType, nFrameLength);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914
Jeff Johnson19b66e82017-10-02 13:25:56 -0700915 if (NULL == adapter) {
916 hdd_err("adapter is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800917 return;
918 }
Jeff Johnson19b66e82017-10-02 13:25:56 -0700919 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800920
921 if (0 == nFrameLength) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700922 hdd_err("Frame Length is Invalid ZERO");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800923 return;
924 }
925
926 if (NULL == pbFrames) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700927 hdd_err("pbFrames is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800928 return;
929 }
930
931 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
932 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
933
Jeff Johnson19b66e82017-10-02 13:25:56 -0700934 /* Get adapter from Destination mac address of the frame */
Sreelakshmi Konamki2b1cd522017-05-26 11:32:44 +0530935 if ((type == SIR_MAC_MGMT_FRAME) &&
936 (subType != SIR_MAC_MGMT_PROBE_REQ) &&
937 !qdf_is_macaddr_broadcast(
938 (struct qdf_mac_addr *)&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET])) {
Jeff Johnson19b66e82017-10-02 13:25:56 -0700939 adapter =
Jeff Johnson7c794a12017-09-03 09:20:55 -0700940 hdd_get_adapter_by_macaddr(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800941 &pbFrames
942 [WLAN_HDD_80211_FRM_DA_OFFSET]);
Jeff Johnson19b66e82017-10-02 13:25:56 -0700943 if (NULL == adapter) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800944 /*
945 * Under assumtion that we don't receive any action
946 * frame with BCST as destination,
947 * we are dropping action frame
948 */
Jeff Johnson19b66e82017-10-02 13:25:56 -0700949 hdd_err("adapter for action frame is NULL Macaddr = "
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700950 MAC_ADDRESS_STR,
951 MAC_ADDR_ARRAY(&pbFrames
952 [WLAN_HDD_80211_FRM_DA_OFFSET]));
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800953 hdd_debug("Frame Type = %d Frame Length = %d subType = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800954 frameType, nFrameLength, subType);
Jeff Johnson3aaa4922017-01-12 08:46:09 -0800955 /*
956 * We will receive broadcast management frames
957 * in OCB mode
958 */
Jeff Johnson19b66e82017-10-02 13:25:56 -0700959 adapter = hdd_get_adapter(hdd_ctx, QDF_OCB_MODE);
960 if (NULL == adapter || !qdf_is_macaddr_broadcast(
Samuel Ahn065e6492016-09-30 22:48:09 +0530961 (struct qdf_mac_addr *)&pbFrames
962 [WLAN_HDD_80211_FRM_DA_OFFSET])) {
963 /*
Jeff Johnson3aaa4922017-01-12 08:46:09 -0800964 * Under assumtion that we don't
965 * receive any action frame with BCST
966 * as destination, we are dropping
967 * action frame
968 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969 return;
Samuel Ahn065e6492016-09-30 22:48:09 +0530970 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 }
972 }
973
Jeff Johnson19b66e82017-10-02 13:25:56 -0700974 if (NULL == adapter->dev) {
975 hdd_err("adapter->dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 return;
977 }
978
Jeff Johnson19b66e82017-10-02 13:25:56 -0700979 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
980 hdd_err("adapter has invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800981 return;
982 }
983
984 /* Channel indicated may be wrong. TODO */
985 /* Indicate an action frame. */
986 if (rxChan <= MAX_NO_OF_2_4_CHANNELS)
987 freq = ieee80211_channel_to_frequency(rxChan,
Dustin Browna30892e2016-10-12 17:28:36 -0700988 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800989 else
990 freq = ieee80211_channel_to_frequency(rxChan,
Dustin Browna30892e2016-10-12 17:28:36 -0700991 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800993 /* Indicate Frame Over Normal Interface */
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800994 hdd_debug("Indicate Frame over NL80211 sessionid : %d, idx :%d",
Jeff Johnson1b780e42017-10-31 14:11:45 -0700995 adapter->session_id, adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800996
997#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
Jeff Johnson19b66e82017-10-02 13:25:56 -0700998 cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr,
Samuel Ahn065e6492016-09-30 22:48:09 +0530999 freq, rxRssi * 100, pbFrames,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001000 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED);
1001#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
Jeff Johnson19b66e82017-10-02 13:25:56 -07001002 cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr,
Samuel Ahn065e6492016-09-30 22:48:09 +05301003 freq, rxRssi * 100, pbFrames,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001004 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED,
1005 GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001006#else
Jeff Johnson19b66e82017-10-02 13:25:56 -07001007 cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr, freq,
Samuel Ahn065e6492016-09-30 22:48:09 +05301008 rxRssi * 100,
1009 pbFrames, nFrameLength, GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001010#endif /* LINUX_VERSION_CODE */
1011}
1012
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001013int wlan_hdd_set_power_save(struct hdd_adapter *adapter,
Wu Gao02bd75b2017-10-13 18:34:02 +08001014 struct p2p_ps_config *ps_config)
Wu Gao9a704f42017-03-10 18:42:11 +08001015{
1016 struct wlan_objmgr_psoc *psoc;
Jeff Johnson18767622017-08-28 11:46:50 -07001017 struct hdd_context *hdd_ctx;
Wu Gao9a704f42017-03-10 18:42:11 +08001018 QDF_STATUS status;
1019
Wu Gao02bd75b2017-10-13 18:34:02 +08001020 if (!adapter || !ps_config) {
1021 hdd_err("null param, adapter:%pK, ps_config:%pK",
1022 adapter, ps_config);
Wu Gao9a704f42017-03-10 18:42:11 +08001023 return -EINVAL;
1024 }
1025
1026 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1027 psoc = hdd_ctx->hdd_psoc;
1028 if (!psoc) {
1029 hdd_err("psoc is null");
1030 return -EINVAL;
1031 }
1032
Wu Gao02bd75b2017-10-13 18:34:02 +08001033 hdd_debug("opp ps:%d, ct window:%d, duration:%d, interval:%d, count:%d, single noa duration:%d, ps selection:%d, vdev id:%d",
1034 ps_config->opp_ps, ps_config->ct_window,
1035 ps_config->duration, ps_config->interval,
1036 ps_config->count, ps_config->single_noa_duration,
1037 ps_config->ps_selection, ps_config->vdev_id);
Wu Gao9a704f42017-03-10 18:42:11 +08001038
Wu Gao02bd75b2017-10-13 18:34:02 +08001039 status = ucfg_p2p_set_ps(psoc, ps_config);
1040 hdd_debug("p2p set power save, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +08001041
1042 return qdf_status_to_os_return(status);
1043}
Wu Gao9a704f42017-03-10 18:42:11 +08001044
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001045int wlan_hdd_listen_offload_start(struct hdd_adapter *adapter,
Wu Gao9a704f42017-03-10 18:42:11 +08001046 struct sir_p2p_lo_start *params)
1047{
1048 struct wlan_objmgr_psoc *psoc;
1049 struct p2p_lo_start lo_start;
Jeff Johnson18767622017-08-28 11:46:50 -07001050 struct hdd_context *hdd_ctx;
Wu Gao9a704f42017-03-10 18:42:11 +08001051 QDF_STATUS status;
1052
1053 if (!adapter || !params) {
Jeff Johnson36e74c42017-09-18 08:15:42 -07001054 hdd_err("null param, adapter:%pK, params:%pK",
Wu Gao9a704f42017-03-10 18:42:11 +08001055 adapter, params);
1056 return -EINVAL;
1057 }
1058
1059 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1060 psoc = hdd_ctx->hdd_psoc;
1061 if (!psoc) {
1062 hdd_err("psoc is null");
1063 return -EINVAL;
1064 }
1065
1066 lo_start.vdev_id = params->vdev_id;
1067 lo_start.ctl_flags = params->ctl_flags;
1068 lo_start.freq = params->freq;
1069 lo_start.period = params->period;
1070 lo_start.interval = params->interval;
1071 lo_start.count = params->count;
1072 lo_start.device_types = params->device_types;
1073 lo_start.dev_types_len = params->dev_types_len;
1074 lo_start.probe_resp_tmplt = params->probe_resp_tmplt;
1075 lo_start.probe_resp_len = params->probe_resp_len;
1076
1077 status = ucfg_p2p_lo_start(psoc, &lo_start);
Wu Gao02bd75b2017-10-13 18:34:02 +08001078 hdd_debug("p2p listen offload start, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +08001079
1080 return qdf_status_to_os_return(status);
1081}
Wu Gao9a704f42017-03-10 18:42:11 +08001082
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001083int wlan_hdd_listen_offload_stop(struct hdd_adapter *adapter)
Wu Gao9a704f42017-03-10 18:42:11 +08001084{
1085 struct wlan_objmgr_psoc *psoc;
Jeff Johnson18767622017-08-28 11:46:50 -07001086 struct hdd_context *hdd_ctx;
Wu Gao9a704f42017-03-10 18:42:11 +08001087 uint32_t vdev_id;
1088 QDF_STATUS status;
1089
1090 if (!adapter) {
Jeff Johnson36e74c42017-09-18 08:15:42 -07001091 hdd_err("adapter is null, adapter:%pK", adapter);
Wu Gao9a704f42017-03-10 18:42:11 +08001092 return -EINVAL;
1093 }
1094
Jeff Johnson1b780e42017-10-31 14:11:45 -07001095 vdev_id = (uint32_t)adapter->session_id;
Wu Gao9a704f42017-03-10 18:42:11 +08001096 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1097 psoc = hdd_ctx->hdd_psoc;
1098 if (!psoc) {
1099 hdd_err("psoc is null");
1100 return -EINVAL;
1101 }
1102
1103 status = ucfg_p2p_lo_stop(psoc, vdev_id);
Wu Gao02bd75b2017-10-13 18:34:02 +08001104 hdd_debug("p2p listen offload stop, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +08001105
1106 return qdf_status_to_os_return(status);
1107}
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001108
1109/**
1110 * wlan_hdd_update_mcc_adaptive_scheduler() - Function to update
1111 * MAS value to FW
1112 * @adapter: adapter object data
1113 * @is_enable: 0-Disable, 1-Enable MAS
1114 *
1115 * This function passes down the value of MAS to UMAC
1116 *
1117 * Return: 0 for success else non zero
1118 *
1119 */
1120static int32_t wlan_hdd_update_mcc_adaptive_scheduler(
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001121 struct hdd_adapter *adapter, bool is_enable)
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001122{
Jeff Johnson18767622017-08-28 11:46:50 -07001123 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001124
1125 if (hdd_ctx == NULL) {
1126 hdd_err("HDD context is null");
1127 return -EINVAL;
1128 }
1129
1130 hdd_info("enable/disable MAS :%d", is_enable);
1131 if (hdd_ctx->config &&
1132 hdd_ctx->config->enableMCCAdaptiveScheduler) {
1133 /* Todo check where to set the MCC apative SCHED for read */
1134
1135 if (QDF_STATUS_SUCCESS != sme_set_mas(is_enable)) {
1136 hdd_err("Failed to enable/disable MAS");
1137 return -EAGAIN;
1138 }
1139 }
1140
1141 return 0;
1142}
1143
1144/**
1145 * wlan_hdd_update_mcc_p2p_quota() - Function to Update P2P
1146 * quota to FW
1147 * @adapter: Pointer to HDD adapter
1148 * @is_set: 0-reset, 1-set
1149 *
1150 * This function passes down the value of MAS to UMAC
1151 *
1152 * Return: none
1153 *
1154 */
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001155static void wlan_hdd_update_mcc_p2p_quota(struct hdd_adapter *adapter,
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001156 bool is_set)
1157{
1158
1159 hdd_info("Set/reset P2P quota: %d", is_set);
1160 if (is_set) {
1161 if (adapter->device_mode == QDF_STA_MODE)
1162 wlan_hdd_set_mcc_p2p_quota(adapter,
1163 100 - HDD_DEFAULT_MCC_P2P_QUOTA
1164 );
1165 else if (adapter->device_mode == QDF_P2P_GO_MODE)
1166 wlan_hdd_go_set_mcc_p2p_quota(adapter,
1167 HDD_DEFAULT_MCC_P2P_QUOTA);
1168 else
1169 wlan_hdd_set_mcc_p2p_quota(adapter,
1170 HDD_DEFAULT_MCC_P2P_QUOTA);
1171 } else {
1172 if (adapter->device_mode == QDF_P2P_GO_MODE)
1173 wlan_hdd_go_set_mcc_p2p_quota(adapter,
1174 HDD_RESET_MCC_P2P_QUOTA);
1175 else
1176 wlan_hdd_set_mcc_p2p_quota(adapter,
1177 HDD_RESET_MCC_P2P_QUOTA);
1178 }
1179}
1180
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001181int32_t wlan_hdd_set_mas(struct hdd_adapter *adapter, uint8_t mas_value)
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001182{
1183 int32_t ret = 0;
1184
1185 if (!adapter) {
1186 hdd_err("Adapter is NULL");
1187 return -EINVAL;
1188 }
1189
1190 if (mas_value) {
1191 hdd_info("Miracast is ON. Disable MAS and configure P2P quota");
1192 ret = wlan_hdd_update_mcc_adaptive_scheduler(
1193 adapter, false);
1194 if (0 != ret) {
1195 hdd_err("Failed to disable MAS");
1196 goto done;
1197 }
1198
1199 /* Config p2p quota */
1200 wlan_hdd_update_mcc_p2p_quota(adapter, true);
1201 } else {
1202 hdd_info("Miracast is OFF. Enable MAS and reset P2P quota");
1203 wlan_hdd_update_mcc_p2p_quota(adapter, false);
1204
1205 ret = wlan_hdd_update_mcc_adaptive_scheduler(
1206 adapter, true);
1207 if (0 != ret) {
1208 hdd_err("Failed to enable MAS");
1209 goto done;
1210 }
1211 }
1212
1213done:
1214 return ret;
1215}
1216
1217/**
1218 * set_first_connection_operating_channel() - Function to set
1219 * first connection oerating channel
1220 * @adapter: adapter data
1221 * @set_value: Quota value for the interface
1222 * @dev_mode: Device mode
1223 * This function is used to set the first adapter operating
1224 * channel
1225 *
1226 * Return: operating channel updated in set value
1227 *
1228 */
1229static uint32_t set_first_connection_operating_channel(
Jeff Johnson18767622017-08-28 11:46:50 -07001230 struct hdd_context *hdd_ctx, uint32_t set_value,
Jeff Johnsonc1e62782017-11-09 09:50:17 -08001231 enum QDF_OPMODE dev_mode)
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001232{
1233 uint8_t operating_channel;
1234
1235 operating_channel = hdd_get_operating_channel(
1236 hdd_ctx, dev_mode);
1237 if (!operating_channel) {
1238 hdd_err(" First adpter operating channel is invalid");
1239 return -EINVAL;
1240 }
1241
1242 hdd_info("First connection channel No.:%d and quota:%dms",
1243 operating_channel, set_value);
1244 /* Move the time quota for first channel to bits 15-8 */
1245 set_value = set_value << 8;
1246
1247 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07001248 * Store the channel number of 1st channel at bits 7-0
1249 * of the bit vector
1250 */
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001251 return set_value | operating_channel;
1252}
1253
1254/**
1255 * set_second_connection_operating_channel() - Function to set
1256 * second connection oerating channel
1257 * @adapter: adapter data
1258 * @set_value: Quota value for the interface
1259 * @vdev_id: vdev id
1260 *
1261 * This function is used to set the first adapter operating
1262 * channel
1263 *
1264 * Return: operating channel updated in set value
1265 *
1266 */
1267static uint32_t set_second_connection_operating_channel(
Jeff Johnson18767622017-08-28 11:46:50 -07001268 struct hdd_context *hdd_ctx, uint32_t set_value,
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001269 uint8_t vdev_id)
1270{
1271 uint8_t operating_channel;
1272
1273 operating_channel = policy_mgr_get_mcc_operating_channel(
1274 hdd_ctx->hdd_psoc, vdev_id);
1275
1276 if (operating_channel == 0) {
1277 hdd_err("Second adapter operating channel is invalid");
1278 return -EINVAL;
1279 }
1280
1281 hdd_info("Second connection channel No.:%d and quota:%dms",
1282 operating_channel, set_value);
1283 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07001284 * Now move the time quota and channel number of the
1285 * 1st adapter to bits 23-16 and bits 15-8 of the bit
1286 * vector, respectively.
1287 */
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001288 set_value = set_value << 8;
1289
1290 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07001291 * Set the channel number for 2nd MCC vdev at bits
1292 * 7-0 of set_value
1293 */
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001294 return set_value | operating_channel;
1295}
1296
1297/**
1298 * wlan_hdd_set_mcc_p2p_quota() - Function to set quota for P2P
1299 * @psoc: PSOC object information
1300 * @set_value: Qouta value for the interface
1301 * @operating_channel First adapter operating channel
1302 * @vdev_id vdev id
1303 *
1304 * This function is used to set the quota for P2P cases
1305 *
1306 * Return: Configuration message posting status, SUCCESS or Fail
1307 *
1308 */
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001309int wlan_hdd_set_mcc_p2p_quota(struct hdd_adapter *adapter,
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001310 uint32_t set_value)
1311{
1312 int32_t ret = 0;
1313 uint32_t concurrent_state;
Jeff Johnson18767622017-08-28 11:46:50 -07001314 struct hdd_context *hdd_ctx;
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001315
1316 if (!adapter) {
1317 hdd_err("Invalid adapter");
1318 return -EFAULT;
1319 }
1320 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1321 if (hdd_ctx == NULL) {
1322 hdd_err("HDD context is null");
1323 return -EINVAL;
1324 }
1325
1326 concurrent_state = policy_mgr_get_concurrency_mode(
1327 hdd_ctx->hdd_psoc);
1328 /*
1329 * Check if concurrency mode is active.
1330 * Need to modify this code to support MCC modes other than STA/P2P
1331 */
1332 if ((concurrent_state ==
1333 (QDF_STA_MASK | QDF_P2P_CLIENT_MASK)) ||
1334 (concurrent_state == (QDF_STA_MASK | QDF_P2P_GO_MASK))) {
1335 hdd_info("STA & P2P are both enabled");
1336
1337 /*
1338 * The channel numbers for both adapters and the time
1339 * quota for the 1st adapter, i.e., one specified in cmd
1340 * are formatted as a bit vector then passed on to WMA
1341 * +***********************************************************+
1342 * |bit 31-24 | bit 23-16 | bits 15-8 | bits 7-0 |
1343 * | Unused | Quota for | chan. # for | chan. # for |
1344 * | | 1st chan. | 1st chan. | 2nd chan. |
1345 * +***********************************************************+
1346 */
1347
1348 set_value = set_first_connection_operating_channel(
1349 hdd_ctx, set_value, adapter->device_mode);
1350
1351
1352 set_value = set_second_connection_operating_channel(
Jeff Johnson1b780e42017-10-31 14:11:45 -07001353 hdd_ctx, set_value, adapter->session_id);
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001354
1355
1356 ret = wlan_hdd_send_p2p_quota(adapter, set_value);
1357 } else {
1358 hdd_info("MCC is not active. Exit w/o setting latency");
1359 }
1360
1361 return ret;
1362}
1363
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001364int wlan_hdd_go_set_mcc_p2p_quota(struct hdd_adapter *hostapd_adapter,
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001365 uint32_t set_value)
1366{
1367 return wlan_hdd_set_mcc_p2p_quota(hostapd_adapter, set_value);
1368}
1369
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001370void wlan_hdd_set_mcc_latency(struct hdd_adapter *adapter, int set_value)
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001371{
1372 uint32_t concurrent_state;
Jeff Johnson18767622017-08-28 11:46:50 -07001373 struct hdd_context *hdd_ctx;
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001374
1375 if (!adapter) {
1376 hdd_err("Invalid adapter");
1377 return;
1378 }
1379
1380 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1381 if (hdd_ctx == NULL) {
1382 hdd_err("HDD context is null");
1383 return;
1384 }
1385
1386 concurrent_state = policy_mgr_get_concurrency_mode(
1387 hdd_ctx->hdd_psoc);
1388 /**
1389 * Check if concurrency mode is active.
1390 * Need to modify this code to support MCC modes other than STA/P2P
1391 */
1392 if ((concurrent_state ==
1393 (QDF_STA_MASK | QDF_P2P_CLIENT_MASK)) ||
1394 (concurrent_state == (QDF_STA_MASK | QDF_P2P_GO_MASK))) {
1395 hdd_info("STA & P2P are both enabled");
1396 /*
1397 * The channel number and latency are formatted in
1398 * a bit vector then passed on to WMA layer.
1399 * +**********************************************+
1400 * |bits 31-16 | bits 15-8 | bits 7-0 |
1401 * | Unused | latency - Chan. 1 | channel no. |
1402 * +**********************************************+
1403 */
1404 set_value = set_first_connection_operating_channel(
1405 hdd_ctx, set_value, adapter->device_mode);
1406
1407 wlan_hdd_send_mcc_latency(adapter, set_value);
1408 } else {
1409 hdd_info("MCC is not active. Exit w/o setting latency");
1410 }
1411}