blob: 580223a05307501f29030c6a4b2f14401158229a [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 *
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019/**
20 *
21 * @file wlan_hdd_p2p.c
22 *
23 * @brief WLAN Host Device Driver implementation for P2P commands interface
24 *
25 */
26
27#include <wlan_hdd_includes.h>
28#include <wlan_hdd_hostapd.h>
29#include <net/cfg80211.h>
30#include "sme_api.h"
31#include "sme_qos_api.h"
32#include "wlan_hdd_p2p.h"
33#include "sap_api.h"
34#include "wlan_hdd_main.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053035#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080036#include <linux/netdevice.h>
37#include <linux/skbuff.h>
38#include <linux/etherdevice.h>
39#include <net/ieee80211_radiotap.h>
40#include "wlan_hdd_tdls.h"
41#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053042#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053043#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080044#include "cds_sched.h"
Tushnim Bhattacharyyade1070d2017-03-09 13:23:55 -080045#include "wlan_policy_mgr_api.h"
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053046#include "cds_utils.h"
Wu Gao9a704f42017-03-10 18:42:11 +080047#include "wlan_p2p_public_struct.h"
48#include "wlan_p2p_ucfg_api.h"
49#include "wlan_cfg80211_p2p.h"
Wu Gaoe5689792018-07-05 19:20:13 +080050#include "wlan_p2p_cfg_api.h"
Wu Gao9a704f42017-03-10 18:42:11 +080051
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +053052/* Ms to Time Unit Micro Sec */
53#define MS_TO_TU_MUS(x) ((x) * 1024)
Archana Ramachandran1e6b9262016-09-30 15:15:10 -070054#define MAX_MUS_VAL (INT_MAX / 1024)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080055
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056#ifdef WLAN_FEATURE_P2P_DEBUG
57#define MAX_P2P_ACTION_FRAME_TYPE 9
58const char *p2p_action_frame_type[] = { "GO Negotiation Request",
59 "GO Negotiation Response",
60 "GO Negotiation Confirmation",
61 "P2P Invitation Request",
62 "P2P Invitation Response",
63 "Device Discoverability Request",
64 "Device Discoverability Response",
65 "Provision Discovery Request",
66 "Provision Discovery Response"};
67
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080068#endif
69#define MAX_TDLS_ACTION_FRAME_TYPE 11
70const char *tdls_action_frame_type[] = { "TDLS Setup Request",
71 "TDLS Setup Response",
72 "TDLS Setup Confirm",
73 "TDLS Teardown",
74 "TDLS Peer Traffic Indication",
75 "TDLS Channel Switch Request",
76 "TDLS Channel Switch Response",
77 "TDLS Peer PSM Request",
78 "TDLS Peer PSM Response",
79 "TDLS Peer Traffic Response",
80 "TDLS Discovery Request"};
81
Jeff Johnson19b66e82017-10-02 13:25:56 -070082void wlan_hdd_cancel_existing_remain_on_channel(struct hdd_adapter *adapter)
Wu Gao8a45ede2017-04-06 20:04:06 +080083{
Jeff Johnson19b66e82017-10-02 13:25:56 -070084 if (!adapter) {
Wu Gao8a45ede2017-04-06 20:04:06 +080085 hdd_err("null adapter");
86 return;
87 }
88
Wu Gao4a1ec8c2018-07-23 19:18:40 +080089 ucfg_p2p_cleanup_roc_by_vdev(adapter->hdd_vdev);
Wu Gao8a45ede2017-04-06 20:04:06 +080090}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091
Jeff Johnson19b66e82017-10-02 13:25:56 -070092int wlan_hdd_check_remain_on_channel(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093{
Wu Gao02bd75b2017-10-13 18:34:02 +080094 if (QDF_P2P_GO_MODE != adapter->device_mode)
95 wlan_hdd_cancel_existing_remain_on_channel(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096
Wu Gao02bd75b2017-10-13 18:34:02 +080097 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098}
99
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100/* Clean up RoC context at hdd_stop_adapter*/
Jeff Johnson19b66e82017-10-02 13:25:56 -0700101void wlan_hdd_cleanup_remain_on_channel_ctx(struct hdd_adapter *adapter)
Wu Gao8a45ede2017-04-06 20:04:06 +0800102{
Jeff Johnson19b66e82017-10-02 13:25:56 -0700103 if (!adapter) {
Wu Gao8a45ede2017-04-06 20:04:06 +0800104 hdd_err("null adapter");
105 return;
106 }
107
Wu Gao4a1ec8c2018-07-23 19:18:40 +0800108 ucfg_p2p_cleanup_roc_by_vdev(adapter->hdd_vdev);
109}
110
111void wlan_hdd_cleanup_actionframe(struct hdd_adapter *adapter)
112{
113 if (!adapter) {
114 hdd_err("null adapter");
115 return;
116 }
117
118 ucfg_p2p_cleanup_tx_by_vdev(adapter->hdd_vdev);
Wu Gao8a45ede2017-04-06 20:04:06 +0800119}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120
Wu Gao9a704f42017-03-10 18:42:11 +0800121static int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
122 struct wireless_dev *wdev,
123 struct ieee80211_channel *chan,
124 unsigned int duration,
125 u64 *cookie)
126{
127 struct net_device *dev = wdev->netdev;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700128 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson18767622017-08-28 11:46:50 -0700129 struct hdd_context *hdd_ctx;
Wu Gao9a704f42017-03-10 18:42:11 +0800130 QDF_STATUS status;
131 int ret;
132
Dustin Brown491d54b2018-03-14 12:39:11 -0700133 hdd_enter();
Wu Gao9a704f42017-03-10 18:42:11 +0800134
Jeff Johnson19b66e82017-10-02 13:25:56 -0700135 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Wu Gao9a704f42017-03-10 18:42:11 +0800136 ret = wlan_hdd_validate_context(hdd_ctx);
137 if (0 != ret)
138 return ret;
139
140 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
141 hdd_err("Command not allowed in FTM mode");
142 return -EINVAL;
143 }
144
Dustin Brown63500612018-08-07 11:36:09 -0700145 if (wlan_hdd_validate_session_id(adapter->session_id))
Wu Gao9a704f42017-03-10 18:42:11 +0800146 return -EINVAL;
Wu Gao9a704f42017-03-10 18:42:11 +0800147
Jeff Johnson19b66e82017-10-02 13:25:56 -0700148 status = wlan_cfg80211_roc(adapter->hdd_vdev, chan,
Wu Gao9a704f42017-03-10 18:42:11 +0800149 duration, cookie);
Wu Gao24466e32018-05-10 19:08:26 +0800150 hdd_debug("remain on channel request, status:%d, cookie:0x%llx",
151 status, *cookie);
Wu Gao9a704f42017-03-10 18:42:11 +0800152
153 return qdf_status_to_os_return(status);
154}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800155
156int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158 struct ieee80211_channel *chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159 unsigned int duration, u64 *cookie)
160{
161 int ret;
162
163 cds_ssr_protect(__func__);
164 ret = __wlan_hdd_cfg80211_remain_on_channel(wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165 wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800166 chan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167 duration, cookie);
168 cds_ssr_unprotect(__func__);
169
170 return ret;
171}
172
Wu Gao9a704f42017-03-10 18:42:11 +0800173static int
174__wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
175 struct wireless_dev *wdev,
176 u64 cookie)
177{
178 QDF_STATUS status;
179 struct net_device *dev = wdev->netdev;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700180 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao9a704f42017-03-10 18:42:11 +0800181
Dustin Brown491d54b2018-03-14 12:39:11 -0700182 hdd_enter();
Wu Gao9a704f42017-03-10 18:42:11 +0800183
184 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
185 hdd_err("Command not allowed in FTM mode");
186 return -EINVAL;
187 }
188
Dustin Brown63500612018-08-07 11:36:09 -0700189 if (wlan_hdd_validate_session_id(adapter->session_id))
Wu Gao9a704f42017-03-10 18:42:11 +0800190 return -EINVAL;
Wu Gao9a704f42017-03-10 18:42:11 +0800191
Jeff Johnson19b66e82017-10-02 13:25:56 -0700192 status = wlan_cfg80211_cancel_roc(adapter->hdd_vdev, cookie);
Wu Gao02bd75b2017-10-13 18:34:02 +0800193 hdd_debug("cancel remain on channel, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +0800194
195 return 0;
196}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197
198int wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800199 struct wireless_dev *wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800200 u64 cookie)
201{
202 int ret;
203
204 cds_ssr_protect(__func__);
205 ret = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800206 wdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207 cookie);
208 cds_ssr_unprotect(__func__);
209
210 return ret;
211}
212
Wu Gao9a704f42017-03-10 18:42:11 +0800213static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
214 struct ieee80211_channel *chan, bool offchan,
215 unsigned int wait,
216 const u8 *buf, size_t len, bool no_cck,
217 bool dont_wait_for_ack, u64 *cookie)
218{
219 QDF_STATUS status;
220 struct net_device *dev = wdev->netdev;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700221 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Will Huang5561cb32018-02-28 15:35:33 +0800222 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Padma, Santhosh Kumar22c462c2018-01-16 17:56:44 +0530223 uint8_t type;
224 uint8_t sub_type;
225 QDF_STATUS qdf_status;
Will Huang5561cb32018-02-28 15:35:33 +0800226 int ret;
Wu Gao9a704f42017-03-10 18:42:11 +0800227
Dustin Brown491d54b2018-03-14 12:39:11 -0700228 hdd_enter();
Wu Gao9a704f42017-03-10 18:42:11 +0800229
230 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
231 hdd_err("Command not allowed in FTM mode");
232 return -EINVAL;
233 }
234
Dustin Brown63500612018-08-07 11:36:09 -0700235 if (wlan_hdd_validate_session_id(adapter->session_id))
Wu Gao9a704f42017-03-10 18:42:11 +0800236 return -EINVAL;
Wu Gao9a704f42017-03-10 18:42:11 +0800237
Will Huang5561cb32018-02-28 15:35:33 +0800238 ret = wlan_hdd_validate_context(hdd_ctx);
239 if (ret) {
240 hdd_err("wlan_hdd_validate_context return:%d", ret);
241 return ret;
242 }
243
Padma, Santhosh Kumar22c462c2018-01-16 17:56:44 +0530244 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
245 sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
246
247 /* When frame to be transmitted is auth mgmt, then trigger
248 * sme_send_mgmt_tx to send auth frame without need for policy manager.
249 * Where as wlan_cfg80211_mgmt_tx requires roc and requires approval
250 * from policy manager.
251 */
252 if ((adapter->device_mode == QDF_STA_MODE) &&
253 (type == SIR_MAC_MGMT_FRAME &&
254 sub_type == SIR_MAC_MGMT_AUTH)) {
Jeff Johnsona96ee932018-06-13 18:12:38 -0700255 qdf_status = sme_send_mgmt_tx(hdd_ctx->mac_handle,
Padma, Santhosh Kumar22c462c2018-01-16 17:56:44 +0530256 adapter->session_id, buf, len);
257
258 if (QDF_IS_STATUS_SUCCESS(qdf_status))
259 return 0;
260 else
261 return -EINVAL;
262 }
263
Jeff Johnson19b66e82017-10-02 13:25:56 -0700264 status = wlan_cfg80211_mgmt_tx(adapter->hdd_vdev, chan,
Wu Gao9a704f42017-03-10 18:42:11 +0800265 offchan, wait, buf, len, no_cck,
266 dont_wait_for_ack, cookie);
Wu Gao24466e32018-05-10 19:08:26 +0800267 hdd_debug("mgmt tx, status:%d, cookie:0x%llx", status, *cookie);
Wu Gao9a704f42017-03-10 18:42:11 +0800268
269 return 0;
270}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800271
272#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
273int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
274 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
Amar Singhal01098f72015-10-08 11:55:32 -0700275#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
277 struct ieee80211_channel *chan, bool offchan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278 unsigned int wait,
279 const u8 *buf, size_t len, bool no_cck,
280 bool dont_wait_for_ack, u64 *cookie)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800281#endif /* LINUX_VERSION_CODE */
282{
283 int ret;
284
285 cds_ssr_protect(__func__);
286
287#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
288 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan,
289 params->wait, params->buf, params->len,
290 params->no_cck, params->dont_wait_for_ack,
291 cookie);
Amar Singhal01098f72015-10-08 11:55:32 -0700292#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293 ret = __wlan_hdd_mgmt_tx(wiphy, wdev, chan, offchan,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800294 wait, buf, len, no_cck,
295 dont_wait_for_ack, cookie);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296#endif /* LINUX_VERSION_CODE */
297 cds_ssr_unprotect(__func__);
298
299 return ret;
300}
301
Wu Gao9a704f42017-03-10 18:42:11 +0800302static int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
303 struct wireless_dev *wdev,
304 u64 cookie)
305{
306 QDF_STATUS status;
307 struct net_device *dev = wdev->netdev;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700308 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao9a704f42017-03-10 18:42:11 +0800309
Dustin Brown491d54b2018-03-14 12:39:11 -0700310 hdd_enter();
Wu Gao9a704f42017-03-10 18:42:11 +0800311
312 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
313 hdd_err("Command not allowed in FTM mode");
314 return -EINVAL;
315 }
316
Dustin Brown63500612018-08-07 11:36:09 -0700317 if (wlan_hdd_validate_session_id(adapter->session_id))
Wu Gao9a704f42017-03-10 18:42:11 +0800318 return -EINVAL;
Wu Gao9a704f42017-03-10 18:42:11 +0800319
Jeff Johnson19b66e82017-10-02 13:25:56 -0700320 status = wlan_cfg80211_mgmt_tx_cancel(adapter->hdd_vdev,
Wu Gao9a704f42017-03-10 18:42:11 +0800321 cookie);
Wu Gao02bd75b2017-10-13 18:34:02 +0800322 hdd_debug("cancel mgmt tx, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +0800323
324 return 0;
325}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800326
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800327int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
328 struct wireless_dev *wdev, u64 cookie)
329{
330 int ret;
331
332 cds_ssr_protect(__func__);
333 ret = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
334 cds_ssr_unprotect(__func__);
335
336 return ret;
337}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800338
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +0530339/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800340 * hdd_set_p2p_noa
341 *
342 ***FUNCTION:
343 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson0f7440e2018-05-06 16:12:39 -0700344 * get P2P_SET_NOA command from wpa_supplicant using private ioctl
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345 *
346 ***LOGIC:
Wu Gao02bd75b2017-10-13 18:34:02 +0800347 * Fill noa Struct According to P2P Power save Option and Pass it to SME layer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800348 *
349 ***ASSUMPTIONS:
350 *
351 *
352 ***NOTE:
353 *
354 * @param dev Pointer to net device structure
355 * @param command Pointer to command
356 *
357 * @return Status
358 */
359
360int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command)
361{
Jeff Johnson19b66e82017-10-02 13:25:56 -0700362 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao02bd75b2017-10-13 18:34:02 +0800363 struct p2p_ps_config noa = {0};
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +0530364 int count, duration, interval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365 char *param;
366 int ret;
367
368 param = strnchr(command, strlen(command), ' ');
369 if (param == NULL) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700370 hdd_err("strnchr failed to find delimeter");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800371 return -EINVAL;
372 }
373 param++;
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +0530374 ret = sscanf(param, "%d %d %d", &count, &interval, &duration);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800375 if (ret != 3) {
Wu Gao02bd75b2017-10-13 18:34:02 +0800376 hdd_err("P2P_SET GO noa: fail to read params, ret=%d",
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700377 ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800378 return -EINVAL;
379 }
Archana Ramachandran1e6b9262016-09-30 15:15:10 -0700380 if (count < 0 || interval < 0 || duration < 0 ||
381 interval > MAX_MUS_VAL || duration > MAX_MUS_VAL) {
382 hdd_err("Invalid NOA parameters");
383 return -EINVAL;
384 }
Wu Gao02bd75b2017-10-13 18:34:02 +0800385 hdd_debug("P2P_SET GO noa: count=%d interval=%d duration=%d",
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700386 count, interval, duration);
Manishekar Chandrasekaran371e5af2016-06-30 23:17:29 +0530387 duration = MS_TO_TU_MUS(duration);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800388 /* PS Selection
Wu Gao02bd75b2017-10-13 18:34:02 +0800389 * Periodic noa (2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 * Single NOA (4)
391 */
Wu Gao02bd75b2017-10-13 18:34:02 +0800392 noa.opp_ps = 0;
393 noa.ct_window = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800394 if (count == 1) {
Wu Gao02bd75b2017-10-13 18:34:02 +0800395 noa.duration = 0;
396 noa.single_noa_duration = duration;
397 noa.ps_selection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800398 } else {
Wu Gao02bd75b2017-10-13 18:34:02 +0800399 noa.duration = duration;
400 noa.single_noa_duration = 0;
401 noa.ps_selection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800402 }
Wu Gao02bd75b2017-10-13 18:34:02 +0800403 noa.interval = MS_TO_TU_MUS(interval);
404 noa.count = count;
Jeff Johnson1b780e42017-10-31 14:11:45 -0700405 noa.vdev_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800406
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800407 hdd_debug("P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 "interval %d count %d single noa duration %d "
Wu Gao02bd75b2017-10-13 18:34:02 +0800409 "PsSelection %x", noa.opp_ps,
410 noa.ct_window, noa.duration, noa.interval,
411 noa.count, noa.single_noa_duration, noa.ps_selection);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800412
Wu Gao02bd75b2017-10-13 18:34:02 +0800413 return wlan_hdd_set_power_save(adapter, &noa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800414}
415
416/**
417 * hdd_set_p2p_opps
418 *
419 ***FUNCTION:
420 * This function is called from hdd_hostapd_ioctl function when Driver
Jeff Johnson0f7440e2018-05-06 16:12:39 -0700421 * get P2P_SET_PS command from wpa_supplicant using private ioctl
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800422 *
423 ***LOGIC:
Wu Gao02bd75b2017-10-13 18:34:02 +0800424 * Fill noa Struct According to P2P Power save Option and Pass it to SME layer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800425 *
426 ***ASSUMPTIONS:
427 *
428 *
429 ***NOTE:
430 *
431 * @param dev Pointer to net device structure
432 * @param command Pointer to command
433 *
434 * @return Status
435 */
436
437int hdd_set_p2p_opps(struct net_device *dev, uint8_t *command)
438{
Jeff Johnsonfbb54522017-08-29 14:25:27 -0700439 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao02bd75b2017-10-13 18:34:02 +0800440 struct p2p_ps_config noa = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441 char *param;
442 int legacy_ps, opp_ps, ctwindow;
443 int ret;
444
445 param = strnchr(command, strlen(command), ' ');
446 if (param == NULL) {
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530447 hdd_err("strnchr failed to find delimiter");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800448 return -EINVAL;
449 }
450 param++;
451 ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
452 if (ret != 3) {
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530453 hdd_err("P2P_SET GO PS: fail to read params, ret=%d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454 return -EINVAL;
455 }
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530456
457 if ((opp_ps != -1) && (opp_ps != 0) && (opp_ps != 1)) {
458 hdd_err("Invalid opp_ps value:%d", opp_ps);
459 return -EINVAL;
460 }
461
462 /* P2P spec: 3.3.2 Power Management and discovery:
463 * CTWindow should be at least 10 TU.
464 * P2P spec: Table 27 - CTWindow and OppPS Parameters field format:
465 * CTWindow and OppPS Parameters together is 8 bits.
466 * CTWindow uses 7 bits (0-6, Bit 7 is for OppPS)
467 * 0 indicates that there shall be no CTWindow
468 */
469 if ((ctwindow != -1) && (ctwindow != 0) &&
470 (!((ctwindow >= 10) && (ctwindow <= 127)))) {
471 hdd_err("Invalid CT window value:%d", ctwindow);
472 return -EINVAL;
473 }
474
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800475 hdd_debug("P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530476 legacy_ps, opp_ps, ctwindow);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800477
478 /* PS Selection
479 * Opportunistic Power Save (1)
480 */
481
Srinivas Girigowdaef327802017-03-24 23:13:20 -0700482 /* From wpa_cli user need to use separate command to set ctWindow and
483 * Opps when user want to set ctWindow during that time other parameters
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800484 * values are coming from wpa_supplicant as -1.
485 * Example : User want to set ctWindow with 30 then wpa_cli command :
486 * P2P_SET ctwindow 30
487 * Command Received at hdd_hostapd_ioctl is as below:
488 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530489 *
490 * e.g., 1: P2P_SET_PS 1 1 30
491 * Driver sets the Opps and CTwindow as 30 and send it to FW.
492 * e.g., 2: P2P_SET_PS 1 -1 15
493 * Driver caches the CTwindow value but not send the command to FW.
494 * e.g., 3: P2P_SET_PS 1 1 -1
495 * Driver sends the command to FW with Opps enabled and CT window as
496 * 15 (last cached CTWindow value).
497 * (or) : P2P_SET_PS 1 1 20
498 * Driver sends the command to FW with opps enabled and CT window
499 * as 20.
500 *
501 * legacy_ps param remains unused until required in the future.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502 */
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530503 if (ctwindow != -1)
504 adapter->ctw = ctwindow;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530506 /* Send command to FW when OppPS is either enabled(1)/disbaled(0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 if (opp_ps != -1) {
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530508 adapter->ops = opp_ps;
509 noa.opp_ps = adapter->ops;
Wu Gao02bd75b2017-10-13 18:34:02 +0800510 noa.ct_window = adapter->ctw;
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530511 noa.duration = 0;
512 noa.single_noa_duration = 0;
513 noa.interval = 0;
514 noa.count = 0;
Wu Gao02bd75b2017-10-13 18:34:02 +0800515 noa.ps_selection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
Jeff Johnson1b780e42017-10-31 14:11:45 -0700516 noa.vdev_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530518 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 +0800519 noa.opp_ps, noa.ct_window,
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530520 noa.duration, noa.interval, noa.count,
521 noa.single_noa_duration,
Wu Gao02bd75b2017-10-13 18:34:02 +0800522 noa.ps_selection);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800523
Wu Gao9a704f42017-03-10 18:42:11 +0800524 wlan_hdd_set_power_save(adapter, &noa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 }
Manishekar Chandrasekaran0575bee2016-07-11 15:25:47 +0530526
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800527 return 0;
528}
529
530int hdd_set_p2p_ps(struct net_device *dev, void *msgData)
531{
Jeff Johnson19b66e82017-10-02 13:25:56 -0700532 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Wu Gao02bd75b2017-10-13 18:34:02 +0800533 struct p2p_ps_config noa = {0};
534 struct p2p_app_set_ps *pappnoa = (struct p2p_app_set_ps *) msgData;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800535
Wu Gao02bd75b2017-10-13 18:34:02 +0800536 noa.opp_ps = pappnoa->opp_ps;
537 noa.ct_window = pappnoa->ctWindow;
538 noa.duration = pappnoa->duration;
539 noa.interval = pappnoa->interval;
540 noa.count = pappnoa->count;
541 noa.single_noa_duration = pappnoa->single_noa_duration;
542 noa.ps_selection = pappnoa->psSelection;
Jeff Johnson1b780e42017-10-31 14:11:45 -0700543 noa.vdev_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800544
Wu Gao02bd75b2017-10-13 18:34:02 +0800545 return wlan_hdd_set_power_save(adapter, &noa);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800546}
547
548static uint8_t wlan_hdd_get_session_type(enum nl80211_iftype type)
549{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800550 switch (type) {
551 case NL80211_IFTYPE_AP:
Dustin Brown0a1da142016-09-13 13:31:52 -0700552 return QDF_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 case NL80211_IFTYPE_P2P_GO:
Dustin Brown0a1da142016-09-13 13:31:52 -0700554 return QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800555 case NL80211_IFTYPE_P2P_CLIENT:
Dustin Brown0a1da142016-09-13 13:31:52 -0700556 return QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557 case NL80211_IFTYPE_STATION:
Dustin Brown0a1da142016-09-13 13:31:52 -0700558 return QDF_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800559 default:
Dustin Brown0a1da142016-09-13 13:31:52 -0700560 return QDF_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562}
563
Ryan Hsu07495ea2016-01-21 15:25:39 -0800564/**
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530565 * wlan_hdd_allow_sap_add() - check to add new sap interface
566 * @hdd_ctx: pointer to hdd context
567 * @name: name of the new interface
568 * @sap_dev: output pointer to hold existing interface
569 *
570 * Return: If able to add interface return true else false
571 */
572static bool
573wlan_hdd_allow_sap_add(struct hdd_context *hdd_ctx, const char *name,
574 struct wireless_dev **sap_dev)
575{
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530576 struct hdd_adapter *adapter;
577
578 *sap_dev = NULL;
Dustin Brown920397d2017-12-13 16:27:50 -0800579
580 hdd_for_each_adapter(hdd_ctx, adapter) {
581 if (adapter->device_mode == QDF_SAP_MODE &&
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530582 test_bit(NET_DEVICE_REGISTERED, &adapter->event_flags) &&
Rajeev Kumar Sirasanagandla0a266172018-05-01 17:55:59 +0530583 adapter->dev &&
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530584 !strncmp(adapter->dev->name, name, IFNAMSIZ)) {
585 struct hdd_beacon_data *beacon =
586 adapter->session.ap.beacon;
587
588 hdd_debug("iface already registered");
589 if (beacon) {
590 adapter->session.ap.beacon = NULL;
591 qdf_mem_free(beacon);
592 }
Rajeev Kumar Sirasanagandla0a266172018-05-01 17:55:59 +0530593 if (adapter->dev->ieee80211_ptr) {
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530594 *sap_dev = adapter->dev->ieee80211_ptr;
595 return false;
596 }
597
598 hdd_err("ieee80211_ptr points to NULL");
599 return false;
600 }
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530601 }
602
603 return true;
604}
605
606/**
Ryan Hsu07495ea2016-01-21 15:25:39 -0800607 * __wlan_hdd_add_virtual_intf() - Add virtual interface
608 * @wiphy: wiphy pointer
609 * @name: User-visible name of the interface
610 * @name_assign_type: the name of assign type of the netdev
611 * @nl80211_iftype: (virtual) interface types
612 * @flags: moniter configuraiton flags (not used)
613 * @vif_params: virtual interface parameters (not used)
614 *
Arun Khandavallic67110c2016-08-18 16:18:51 +0530615 * Return: the pointer of wireless dev, otherwise ERR_PTR.
Ryan Hsu07495ea2016-01-21 15:25:39 -0800616 */
Jeff Johnsond2291042016-10-05 16:18:50 -0700617static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
619 const char *name,
Ryan Hsu07495ea2016-01-21 15:25:39 -0800620 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800621 enum nl80211_iftype type,
622 u32 *flags,
623 struct vif_params *params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624{
Jeff Johnson7c794a12017-09-03 09:20:55 -0700625 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
Jeff Johnson19b66e82017-10-02 13:25:56 -0700626 struct hdd_adapter *adapter = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627 int ret;
Peng Xu45486ea2015-11-12 16:37:44 -0800628 uint8_t session_type;
Wu Gaoe5689792018-07-05 19:20:13 +0800629 bool p2p_dev_addr_admin = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800630
Dustin Brown491d54b2018-03-14 12:39:11 -0700631 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632
Anurag Chouhan6d760662016-02-20 16:05:43 +0530633 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700634 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800635 return ERR_PTR(-EINVAL);
636 }
637
Jeff Johnson7c794a12017-09-03 09:20:55 -0700638 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +0530639 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800640 return ERR_PTR(ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800641
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530642 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800643 TRACE_CODE_HDD_ADD_VIRTUAL_INTF, NO_SESSION, type));
644 /*
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800645 * Allow addition multiple interfaces for QDF_P2P_GO_MODE,
646 * QDF_SAP_MODE, QDF_P2P_CLIENT_MODE and QDF_STA_MODE
Peng Xu45486ea2015-11-12 16:37:44 -0800647 * session type.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800648 */
Peng Xu45486ea2015-11-12 16:37:44 -0800649 session_type = wlan_hdd_get_session_type(type);
Jeff Johnson7c794a12017-09-03 09:20:55 -0700650 if (hdd_get_adapter(hdd_ctx, session_type) != NULL
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800651 && QDF_SAP_MODE != session_type
652 && QDF_P2P_GO_MODE != session_type
Krunal Sonifb84cbd2016-03-10 13:09:07 -0800653 && QDF_P2P_CLIENT_MODE != session_type
654 && QDF_STA_MODE != session_type) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700655 hdd_err("Interface type %d already exists. Two interfaces of same type are not supported currently.",
656 type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800657 return ERR_PTR(-EINVAL);
658 }
659
Jeff Johnson19b66e82017-10-02 13:25:56 -0700660 adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
Dustin Brown63500612018-08-07 11:36:09 -0700661 if (adapter && !wlan_hdd_validate_session_id(adapter->session_id)) {
Sandeep Puligilla5f86d992017-10-29 14:58:53 -0700662 if (ucfg_scan_get_vdev_status(adapter->hdd_vdev) !=
663 SCAN_NOT_IN_PROGRESS) {
Jeff Johnson7c794a12017-09-03 09:20:55 -0700664 wlan_abort_scan(hdd_ctx->hdd_pdev, INVAL_PDEV_ID,
Jeff Johnson1b780e42017-10-31 14:11:45 -0700665 adapter->session_id, INVALID_SCAN_ID, false);
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800666 hdd_debug("Abort Scan while adding virtual interface");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800667 }
668 }
669
Hanumanth Reddy Pothula74a97d42017-11-20 21:43:54 +0530670 if (session_type == QDF_SAP_MODE) {
Rajeev Kumar Sirasanagandlabb03b2c2017-12-12 17:51:09 +0530671 struct wireless_dev *sap_dev;
672 bool allow_add_sap = wlan_hdd_allow_sap_add(hdd_ctx, name,
673 &sap_dev);
674 if (!allow_add_sap) {
675 if (sap_dev)
676 return sap_dev;
Hanumanth Reddy Pothula74a97d42017-11-20 21:43:54 +0530677
Hanumanth Reddy Pothula74a97d42017-11-20 21:43:54 +0530678 return ERR_PTR(-EINVAL);
679 }
680 }
681
Jeff Johnson19b66e82017-10-02 13:25:56 -0700682 adapter = NULL;
Wu Gaoe5689792018-07-05 19:20:13 +0800683 cfg_p2p_get_device_addr_admin(hdd_ctx->hdd_psoc, &p2p_dev_addr_admin);
684 if (p2p_dev_addr_admin &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 ((NL80211_IFTYPE_P2P_GO == type) ||
686 (NL80211_IFTYPE_P2P_CLIENT == type))) {
687 /*
688 * Generate the P2P Interface Address. this address must be
689 * different from the P2P Device Address.
690 */
Jeff Johnsonacbdb1c2017-11-02 20:42:02 -0700691 struct qdf_mac_addr p2p_device_address =
692 hdd_ctx->p2p_device_address;
693 p2p_device_address.bytes[4] ^= 0x80;
Jeff Johnson19b66e82017-10-02 13:25:56 -0700694 adapter = hdd_open_adapter(hdd_ctx,
Dustin Brown0a1da142016-09-13 13:31:52 -0700695 session_type,
Jeff Johnsonacbdb1c2017-11-02 20:42:02 -0700696 name, p2p_device_address.bytes,
Ryan Hsu07495ea2016-01-21 15:25:39 -0800697 name_assign_type,
698 true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 } else {
Jeff Johnson19b66e82017-10-02 13:25:56 -0700700 adapter = hdd_open_adapter(hdd_ctx,
Dustin Brown0a1da142016-09-13 13:31:52 -0700701 session_type,
Ryan Hsu07495ea2016-01-21 15:25:39 -0800702 name,
Jeff Johnson7c794a12017-09-03 09:20:55 -0700703 wlan_hdd_get_intf_addr(hdd_ctx),
Ryan Hsu07495ea2016-01-21 15:25:39 -0800704 name_assign_type,
705 true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 }
707
Jeff Johnson19b66e82017-10-02 13:25:56 -0700708 if (NULL == adapter) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700709 hdd_err("hdd_open_adapter failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 return ERR_PTR(-ENOSPC);
711 }
Nirav Shahbd36b062016-07-18 11:12:59 +0530712
Arun Khandavalli99286452016-08-22 12:13:41 +0530713 /*
714 * Add interface can be requested from the upper layer at any time
715 * check the statemachine for modules state and if they are closed
716 * open the modules.
717 */
Dustin Browne7e71d32018-05-11 16:00:08 -0700718 ret = hdd_wlan_start_modules(hdd_ctx, false);
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530719 if (ret) {
720 hdd_err("Failed to start the wlan_modules");
721 goto close_adapter;
722 }
Arun Khandavalli99286452016-08-22 12:13:41 +0530723
Arun Khandavalli812d0692016-09-01 19:11:56 +0530724 /*
725 * Once the support for session creation/deletion from
726 * hdd_hostapd_open/hdd_host_stop is in place.
727 * The support for starting adapter from here can be removed.
728 */
729 if (NL80211_IFTYPE_AP == type || (NL80211_IFTYPE_P2P_GO == type)) {
Jeff Johnson19b66e82017-10-02 13:25:56 -0700730 ret = hdd_start_adapter(adapter);
Arun Khandavallic67110c2016-08-18 16:18:51 +0530731 if (ret) {
732 hdd_err("Failed to start %s", name);
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530733 goto stop_modules;
Arun Khandavallic67110c2016-08-18 16:18:51 +0530734 }
735 }
736
Jeff Johnson7c794a12017-09-03 09:20:55 -0700737 if (hdd_ctx->rps)
Jeff Johnson19b66e82017-10-02 13:25:56 -0700738 hdd_send_rps_ind(adapter);
Nirav Shahbd36b062016-07-18 11:12:59 +0530739
Dustin Browne74003f2018-03-14 12:51:58 -0700740 hdd_exit();
Jeff Johnson19b66e82017-10-02 13:25:56 -0700741 return adapter->dev->ieee80211_ptr;
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530742
743stop_modules:
744 /*
745 * Find if any iface is up. If there is not iface which is up
746 * start the timer to close the modules
747 */
Jeff Johnson7c794a12017-09-03 09:20:55 -0700748 if (hdd_check_for_opened_interfaces(hdd_ctx)) {
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800749 hdd_debug("Closing all modules from the add_virt_iface");
Dustin Brown6f427922017-09-19 12:19:00 -0700750 qdf_sched_delayed_work(&hdd_ctx->iface_idle_work,
751 hdd_ctx->config->iface_change_wait_time);
Mukul Sharma07bd8752017-10-10 16:58:14 +0530752 hdd_prevent_suspend_timeout(
753 hdd_ctx->config->iface_change_wait_time,
754 WIFI_POWER_EVENT_WAKELOCK_IFACE_CHANGE_TIMER);
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530755 } else
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800756 hdd_debug("Other interfaces are still up dont close modules!");
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530757
758close_adapter:
Jeff Johnson19b66e82017-10-02 13:25:56 -0700759 hdd_close_adapter(hdd_ctx, adapter, true);
Ashish Kumar Dhanotiya486c13a2017-03-03 12:57:56 +0530760
761 return ERR_PTR(-EINVAL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762}
763
Dustin Brown9ed30a52017-08-16 13:59:38 -0700764#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
765struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
766 const char *name,
767 unsigned char name_assign_type,
768 enum nl80211_iftype type,
769 struct vif_params *params)
770{
771 struct wireless_dev *wdev;
772
773 cds_ssr_protect(__func__);
774 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
775 type, &params->flags, params);
776 cds_ssr_unprotect(__func__);
777
778 return wdev;
779}
780#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || defined(WITH_BACKPORTS)
Ryan Hsu07495ea2016-01-21 15:25:39 -0800781/**
782 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
783 * @wiphy: wiphy pointer
784 * @name: User-visible name of the interface
785 * @name_assign_type: the name of assign type of the netdev
786 * @nl80211_iftype: (virtual) interface types
787 * @flags: monitor mode configuration flags (not used)
788 * @vif_params: virtual interface parameters (not used)
789 *
Arun Khandavallic67110c2016-08-18 16:18:51 +0530790 * Return: the pointer of wireless dev, otherwise ERR_PTR.
Ryan Hsu07495ea2016-01-21 15:25:39 -0800791 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800792struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
793 const char *name,
Ryan Hsu07495ea2016-01-21 15:25:39 -0800794 unsigned char name_assign_type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800795 enum nl80211_iftype type,
796 u32 *flags,
797 struct vif_params *params)
798{
799 struct wireless_dev *wdev;
800
801 cds_ssr_protect(__func__);
Ryan Hsu07495ea2016-01-21 15:25:39 -0800802 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
803 type, flags, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800804 cds_ssr_unprotect(__func__);
805 return wdev;
Ryan Hsu07495ea2016-01-21 15:25:39 -0800806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807}
Ryan Hsu07495ea2016-01-21 15:25:39 -0800808#else
809/**
810 * wlan_hdd_add_virtual_intf() - Add virtual interface wrapper
811 * @wiphy: wiphy pointer
812 * @name: User-visible name of the interface
813 * @nl80211_iftype: (virtual) interface types
814 * @flags: monitor mode configuration flags (not used)
815 * @vif_params: virtual interface parameters (not used)
816 *
Arun Khandavallic67110c2016-08-18 16:18:51 +0530817 * Return: the pointer of wireless dev, otherwise ERR_PTR.
Ryan Hsu07495ea2016-01-21 15:25:39 -0800818 */
819struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
820 const char *name,
821 enum nl80211_iftype type,
822 u32 *flags,
823 struct vif_params *params)
824{
825 struct wireless_dev *wdev;
826 unsigned char name_assign_type = 0;
827
828 cds_ssr_protect(__func__);
829 wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
830 type, flags, params);
831 cds_ssr_unprotect(__func__);
832 return wdev;
833
834}
835#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800836
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800839 struct net_device *dev = wdev->netdev;
Jeff Johnson7c794a12017-09-03 09:20:55 -0700840 struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
Jeff Johnsona96ee932018-06-13 18:12:38 -0700841 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
842 int errno;
Srinivas Girigowdaef327802017-03-24 23:13:20 -0700843
Dustin Brown491d54b2018-03-14 12:39:11 -0700844 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800845
Anurag Chouhan6d760662016-02-20 16:05:43 +0530846 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700847 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800848 return -EINVAL;
849 }
850
Hanumanth Reddy Pothula74a97d42017-11-20 21:43:54 +0530851 /*
852 * Clear SOFTAP_INIT_DONE flag to mark SAP unload, so that we do
853 * not restart SAP after SSR as SAP is already stopped from user space.
854 */
Jeff Johnsona96ee932018-06-13 18:12:38 -0700855 clear_bit(SOFTAP_INIT_DONE, &adapter->event_flags);
Hanumanth Reddy Pothula74a97d42017-11-20 21:43:54 +0530856
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530857 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800858 TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
Jeff Johnsona96ee932018-06-13 18:12:38 -0700859 adapter->session_id, adapter->device_mode));
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800860 hdd_debug("Device_mode %s(%d)",
Jeff Johnsona96ee932018-06-13 18:12:38 -0700861 hdd_device_mode_to_string(adapter->device_mode),
862 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800863
Jeff Johnsona96ee932018-06-13 18:12:38 -0700864 errno = wlan_hdd_validate_context(hdd_ctx);
865 if (errno)
866 return errno;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867
Mukul Sharma24699bd2017-04-03 19:50:44 +0530868 /* check state machine state and kickstart modules if they are closed */
Jeff Johnsona96ee932018-06-13 18:12:38 -0700869 errno = hdd_wlan_start_modules(hdd_ctx, false);
870 if (errno)
871 return errno;
Arun Khandavalli99286452016-08-22 12:13:41 +0530872
Jeff Johnsona96ee932018-06-13 18:12:38 -0700873 if (adapter->device_mode == QDF_SAP_MODE &&
874 wlan_sap_is_pre_cac_active(hdd_ctx->mac_handle)) {
Jeff Johnson7c794a12017-09-03 09:20:55 -0700875 hdd_clean_up_pre_cac_interface(hdd_ctx);
Mukul Sharma24699bd2017-04-03 19:50:44 +0530876 } else {
Jeff Johnson7c794a12017-09-03 09:20:55 -0700877 wlan_hdd_release_intf_addr(hdd_ctx,
Jeff Johnsona96ee932018-06-13 18:12:38 -0700878 adapter->mac_addr.bytes);
879 hdd_stop_adapter(hdd_ctx, adapter);
880 hdd_deinit_adapter(hdd_ctx, adapter, true);
881 hdd_close_adapter(hdd_ctx, adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +0530882 }
883
Dustin Browne74003f2018-03-14 12:51:58 -0700884 hdd_exit();
Mukul Sharma24699bd2017-04-03 19:50:44 +0530885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800886 return 0;
887}
888
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800889int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800890{
891 int ret;
892
893 cds_ssr_protect(__func__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894 ret = __wlan_hdd_del_virtual_intf(wiphy, wdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800895 cds_ssr_unprotect(__func__);
896
897 return ret;
898}
899
Jeff Johnson19b66e82017-10-02 13:25:56 -0700900void __hdd_indicate_mgmt_frame(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800901 uint32_t nFrameLength,
902 uint8_t *pbFrames,
903 uint8_t frameType, uint32_t rxChan, int8_t rxRssi)
904{
905 uint16_t freq;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906 uint8_t type = 0;
907 uint8_t subType = 0;
Jeff Johnson7c794a12017-09-03 09:20:55 -0700908 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800909
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800910 hdd_debug("Frame Type = %d Frame Length = %d",
Samuel Ahn065e6492016-09-30 22:48:09 +0530911 frameType, nFrameLength);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800912
Jeff Johnson19b66e82017-10-02 13:25:56 -0700913 if (NULL == adapter) {
914 hdd_err("adapter is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800915 return;
916 }
Jeff Johnson19b66e82017-10-02 13:25:56 -0700917 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800918
919 if (0 == nFrameLength) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700920 hdd_err("Frame Length is Invalid ZERO");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800921 return;
922 }
923
924 if (NULL == pbFrames) {
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700925 hdd_err("pbFrames is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800926 return;
927 }
928
929 type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]);
930 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]);
931
Jeff Johnson19b66e82017-10-02 13:25:56 -0700932 /* Get adapter from Destination mac address of the frame */
Sreelakshmi Konamki2b1cd522017-05-26 11:32:44 +0530933 if ((type == SIR_MAC_MGMT_FRAME) &&
934 (subType != SIR_MAC_MGMT_PROBE_REQ) &&
935 !qdf_is_macaddr_broadcast(
936 (struct qdf_mac_addr *)&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET])) {
Jeff Johnson19b66e82017-10-02 13:25:56 -0700937 adapter =
Jeff Johnson7c794a12017-09-03 09:20:55 -0700938 hdd_get_adapter_by_macaddr(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800939 &pbFrames
940 [WLAN_HDD_80211_FRM_DA_OFFSET]);
Jeff Johnson19b66e82017-10-02 13:25:56 -0700941 if (NULL == adapter) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800942 /*
943 * Under assumtion that we don't receive any action
944 * frame with BCST as destination,
945 * we are dropping action frame
946 */
Jeff Johnson19b66e82017-10-02 13:25:56 -0700947 hdd_err("adapter for action frame is NULL Macaddr = "
Archana Ramachandrandfb6f852016-08-19 17:25:29 -0700948 MAC_ADDRESS_STR,
949 MAC_ADDR_ARRAY(&pbFrames
950 [WLAN_HDD_80211_FRM_DA_OFFSET]));
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800951 hdd_debug("Frame Type = %d Frame Length = %d subType = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800952 frameType, nFrameLength, subType);
Jeff Johnson3aaa4922017-01-12 08:46:09 -0800953 /*
954 * We will receive broadcast management frames
955 * in OCB mode
956 */
Jeff Johnson19b66e82017-10-02 13:25:56 -0700957 adapter = hdd_get_adapter(hdd_ctx, QDF_OCB_MODE);
958 if (NULL == adapter || !qdf_is_macaddr_broadcast(
Samuel Ahn065e6492016-09-30 22:48:09 +0530959 (struct qdf_mac_addr *)&pbFrames
960 [WLAN_HDD_80211_FRM_DA_OFFSET])) {
961 /*
Jeff Johnson3aaa4922017-01-12 08:46:09 -0800962 * Under assumtion that we don't
963 * receive any action frame with BCST
964 * as destination, we are dropping
965 * action frame
966 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800967 return;
Samuel Ahn065e6492016-09-30 22:48:09 +0530968 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800969 }
970 }
971
Jeff Johnson19b66e82017-10-02 13:25:56 -0700972 if (NULL == adapter->dev) {
973 hdd_err("adapter->dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974 return;
975 }
976
Jeff Johnson19b66e82017-10-02 13:25:56 -0700977 if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
978 hdd_err("adapter has invalid magic");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800979 return;
980 }
981
982 /* Channel indicated may be wrong. TODO */
983 /* Indicate an action frame. */
984 if (rxChan <= MAX_NO_OF_2_4_CHANNELS)
985 freq = ieee80211_channel_to_frequency(rxChan,
Dustin Browna30892e2016-10-12 17:28:36 -0700986 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800987 else
988 freq = ieee80211_channel_to_frequency(rxChan,
Dustin Browna30892e2016-10-12 17:28:36 -0700989 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800990
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991 /* Indicate Frame Over Normal Interface */
Srinivas Girigowdac7f00d42017-03-06 18:01:35 -0800992 hdd_debug("Indicate Frame over NL80211 sessionid : %d, idx :%d",
Jeff Johnson1b780e42017-10-31 14:11:45 -0700993 adapter->session_id, adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800994
995#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
Jeff Johnson19b66e82017-10-02 13:25:56 -0700996 cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr,
Samuel Ahn065e6492016-09-30 22:48:09 +0530997 freq, rxRssi * 100, pbFrames,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800998 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED);
999#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
Jeff Johnson19b66e82017-10-02 13:25:56 -07001000 cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr,
Samuel Ahn065e6492016-09-30 22:48:09 +05301001 freq, rxRssi * 100, pbFrames,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001002 nFrameLength, NL80211_RXMGMT_FLAG_ANSWERED,
1003 GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001004#else
Jeff Johnson19b66e82017-10-02 13:25:56 -07001005 cfg80211_rx_mgmt(adapter->dev->ieee80211_ptr, freq,
Samuel Ahn065e6492016-09-30 22:48:09 +05301006 rxRssi * 100,
1007 pbFrames, nFrameLength, GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001008#endif /* LINUX_VERSION_CODE */
1009}
1010
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001011int wlan_hdd_set_power_save(struct hdd_adapter *adapter,
Wu Gao02bd75b2017-10-13 18:34:02 +08001012 struct p2p_ps_config *ps_config)
Wu Gao9a704f42017-03-10 18:42:11 +08001013{
1014 struct wlan_objmgr_psoc *psoc;
Jeff Johnson18767622017-08-28 11:46:50 -07001015 struct hdd_context *hdd_ctx;
Wu Gao9a704f42017-03-10 18:42:11 +08001016 QDF_STATUS status;
1017
Wu Gao02bd75b2017-10-13 18:34:02 +08001018 if (!adapter || !ps_config) {
1019 hdd_err("null param, adapter:%pK, ps_config:%pK",
1020 adapter, ps_config);
Wu Gao9a704f42017-03-10 18:42:11 +08001021 return -EINVAL;
1022 }
1023
1024 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1025 psoc = hdd_ctx->hdd_psoc;
1026 if (!psoc) {
1027 hdd_err("psoc is null");
1028 return -EINVAL;
1029 }
1030
Wu Gao02bd75b2017-10-13 18:34:02 +08001031 hdd_debug("opp ps:%d, ct window:%d, duration:%d, interval:%d, count:%d, single noa duration:%d, ps selection:%d, vdev id:%d",
1032 ps_config->opp_ps, ps_config->ct_window,
1033 ps_config->duration, ps_config->interval,
1034 ps_config->count, ps_config->single_noa_duration,
1035 ps_config->ps_selection, ps_config->vdev_id);
Wu Gao9a704f42017-03-10 18:42:11 +08001036
Wu Gao02bd75b2017-10-13 18:34:02 +08001037 status = ucfg_p2p_set_ps(psoc, ps_config);
1038 hdd_debug("p2p set power save, status:%d", status);
Wu Gao9a704f42017-03-10 18:42:11 +08001039
1040 return qdf_status_to_os_return(status);
1041}
Wu Gao9a704f42017-03-10 18:42:11 +08001042
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001043/**
1044 * wlan_hdd_update_mcc_adaptive_scheduler() - Function to update
1045 * MAS value to FW
1046 * @adapter: adapter object data
1047 * @is_enable: 0-Disable, 1-Enable MAS
1048 *
1049 * This function passes down the value of MAS to UMAC
1050 *
1051 * Return: 0 for success else non zero
1052 *
1053 */
1054static int32_t wlan_hdd_update_mcc_adaptive_scheduler(
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001055 struct hdd_adapter *adapter, bool is_enable)
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001056{
Jeff Johnson18767622017-08-28 11:46:50 -07001057 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001058
1059 if (hdd_ctx == NULL) {
1060 hdd_err("HDD context is null");
1061 return -EINVAL;
1062 }
1063
1064 hdd_info("enable/disable MAS :%d", is_enable);
1065 if (hdd_ctx->config &&
1066 hdd_ctx->config->enableMCCAdaptiveScheduler) {
1067 /* Todo check where to set the MCC apative SCHED for read */
1068
1069 if (QDF_STATUS_SUCCESS != sme_set_mas(is_enable)) {
1070 hdd_err("Failed to enable/disable MAS");
1071 return -EAGAIN;
1072 }
1073 }
1074
1075 return 0;
1076}
1077
1078/**
1079 * wlan_hdd_update_mcc_p2p_quota() - Function to Update P2P
1080 * quota to FW
1081 * @adapter: Pointer to HDD adapter
1082 * @is_set: 0-reset, 1-set
1083 *
1084 * This function passes down the value of MAS to UMAC
1085 *
1086 * Return: none
1087 *
1088 */
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001089static void wlan_hdd_update_mcc_p2p_quota(struct hdd_adapter *adapter,
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001090 bool is_set)
1091{
1092
1093 hdd_info("Set/reset P2P quota: %d", is_set);
1094 if (is_set) {
1095 if (adapter->device_mode == QDF_STA_MODE)
1096 wlan_hdd_set_mcc_p2p_quota(adapter,
1097 100 - HDD_DEFAULT_MCC_P2P_QUOTA
1098 );
1099 else if (adapter->device_mode == QDF_P2P_GO_MODE)
1100 wlan_hdd_go_set_mcc_p2p_quota(adapter,
1101 HDD_DEFAULT_MCC_P2P_QUOTA);
1102 else
1103 wlan_hdd_set_mcc_p2p_quota(adapter,
1104 HDD_DEFAULT_MCC_P2P_QUOTA);
1105 } else {
1106 if (adapter->device_mode == QDF_P2P_GO_MODE)
1107 wlan_hdd_go_set_mcc_p2p_quota(adapter,
1108 HDD_RESET_MCC_P2P_QUOTA);
1109 else
1110 wlan_hdd_set_mcc_p2p_quota(adapter,
1111 HDD_RESET_MCC_P2P_QUOTA);
1112 }
1113}
1114
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001115int32_t wlan_hdd_set_mas(struct hdd_adapter *adapter, uint8_t mas_value)
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001116{
1117 int32_t ret = 0;
1118
1119 if (!adapter) {
1120 hdd_err("Adapter is NULL");
1121 return -EINVAL;
1122 }
1123
1124 if (mas_value) {
1125 hdd_info("Miracast is ON. Disable MAS and configure P2P quota");
1126 ret = wlan_hdd_update_mcc_adaptive_scheduler(
1127 adapter, false);
1128 if (0 != ret) {
1129 hdd_err("Failed to disable MAS");
1130 goto done;
1131 }
1132
1133 /* Config p2p quota */
1134 wlan_hdd_update_mcc_p2p_quota(adapter, true);
1135 } else {
1136 hdd_info("Miracast is OFF. Enable MAS and reset P2P quota");
1137 wlan_hdd_update_mcc_p2p_quota(adapter, false);
1138
1139 ret = wlan_hdd_update_mcc_adaptive_scheduler(
1140 adapter, true);
1141 if (0 != ret) {
1142 hdd_err("Failed to enable MAS");
1143 goto done;
1144 }
1145 }
1146
1147done:
1148 return ret;
1149}
1150
1151/**
1152 * set_first_connection_operating_channel() - Function to set
1153 * first connection oerating channel
1154 * @adapter: adapter data
1155 * @set_value: Quota value for the interface
1156 * @dev_mode: Device mode
1157 * This function is used to set the first adapter operating
1158 * channel
1159 *
1160 * Return: operating channel updated in set value
1161 *
1162 */
1163static uint32_t set_first_connection_operating_channel(
Jeff Johnson18767622017-08-28 11:46:50 -07001164 struct hdd_context *hdd_ctx, uint32_t set_value,
Jeff Johnsonc1e62782017-11-09 09:50:17 -08001165 enum QDF_OPMODE dev_mode)
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001166{
1167 uint8_t operating_channel;
1168
1169 operating_channel = hdd_get_operating_channel(
1170 hdd_ctx, dev_mode);
1171 if (!operating_channel) {
1172 hdd_err(" First adpter operating channel is invalid");
1173 return -EINVAL;
1174 }
1175
1176 hdd_info("First connection channel No.:%d and quota:%dms",
1177 operating_channel, set_value);
1178 /* Move the time quota for first channel to bits 15-8 */
1179 set_value = set_value << 8;
1180
1181 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07001182 * Store the channel number of 1st channel at bits 7-0
1183 * of the bit vector
1184 */
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001185 return set_value | operating_channel;
1186}
1187
1188/**
1189 * set_second_connection_operating_channel() - Function to set
1190 * second connection oerating channel
1191 * @adapter: adapter data
1192 * @set_value: Quota value for the interface
1193 * @vdev_id: vdev id
1194 *
1195 * This function is used to set the first adapter operating
1196 * channel
1197 *
1198 * Return: operating channel updated in set value
1199 *
1200 */
1201static uint32_t set_second_connection_operating_channel(
Jeff Johnson18767622017-08-28 11:46:50 -07001202 struct hdd_context *hdd_ctx, uint32_t set_value,
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001203 uint8_t vdev_id)
1204{
1205 uint8_t operating_channel;
1206
1207 operating_channel = policy_mgr_get_mcc_operating_channel(
1208 hdd_ctx->hdd_psoc, vdev_id);
1209
1210 if (operating_channel == 0) {
1211 hdd_err("Second adapter operating channel is invalid");
1212 return -EINVAL;
1213 }
1214
1215 hdd_info("Second connection channel No.:%d and quota:%dms",
1216 operating_channel, set_value);
1217 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07001218 * Now move the time quota and channel number of the
1219 * 1st adapter to bits 23-16 and bits 15-8 of the bit
1220 * vector, respectively.
1221 */
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001222 set_value = set_value << 8;
1223
1224 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -07001225 * Set the channel number for 2nd MCC vdev at bits
1226 * 7-0 of set_value
1227 */
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001228 return set_value | operating_channel;
1229}
1230
1231/**
1232 * wlan_hdd_set_mcc_p2p_quota() - Function to set quota for P2P
1233 * @psoc: PSOC object information
1234 * @set_value: Qouta value for the interface
1235 * @operating_channel First adapter operating channel
1236 * @vdev_id vdev id
1237 *
1238 * This function is used to set the quota for P2P cases
1239 *
1240 * Return: Configuration message posting status, SUCCESS or Fail
1241 *
1242 */
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001243int wlan_hdd_set_mcc_p2p_quota(struct hdd_adapter *adapter,
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001244 uint32_t set_value)
1245{
1246 int32_t ret = 0;
1247 uint32_t concurrent_state;
Jeff Johnson18767622017-08-28 11:46:50 -07001248 struct hdd_context *hdd_ctx;
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001249
1250 if (!adapter) {
1251 hdd_err("Invalid adapter");
1252 return -EFAULT;
1253 }
1254 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1255 if (hdd_ctx == NULL) {
1256 hdd_err("HDD context is null");
1257 return -EINVAL;
1258 }
1259
1260 concurrent_state = policy_mgr_get_concurrency_mode(
1261 hdd_ctx->hdd_psoc);
1262 /*
1263 * Check if concurrency mode is active.
1264 * Need to modify this code to support MCC modes other than STA/P2P
1265 */
1266 if ((concurrent_state ==
1267 (QDF_STA_MASK | QDF_P2P_CLIENT_MASK)) ||
1268 (concurrent_state == (QDF_STA_MASK | QDF_P2P_GO_MASK))) {
1269 hdd_info("STA & P2P are both enabled");
1270
1271 /*
1272 * The channel numbers for both adapters and the time
1273 * quota for the 1st adapter, i.e., one specified in cmd
1274 * are formatted as a bit vector then passed on to WMA
1275 * +***********************************************************+
1276 * |bit 31-24 | bit 23-16 | bits 15-8 | bits 7-0 |
1277 * | Unused | Quota for | chan. # for | chan. # for |
1278 * | | 1st chan. | 1st chan. | 2nd chan. |
1279 * +***********************************************************+
1280 */
1281
1282 set_value = set_first_connection_operating_channel(
1283 hdd_ctx, set_value, adapter->device_mode);
1284
1285
1286 set_value = set_second_connection_operating_channel(
Jeff Johnson1b780e42017-10-31 14:11:45 -07001287 hdd_ctx, set_value, adapter->session_id);
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001288
1289
1290 ret = wlan_hdd_send_p2p_quota(adapter, set_value);
1291 } else {
1292 hdd_info("MCC is not active. Exit w/o setting latency");
1293 }
1294
1295 return ret;
1296}
1297
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001298int wlan_hdd_go_set_mcc_p2p_quota(struct hdd_adapter *hostapd_adapter,
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001299 uint32_t set_value)
1300{
1301 return wlan_hdd_set_mcc_p2p_quota(hostapd_adapter, set_value);
1302}
1303
Jeff Johnsonfbb54522017-08-29 14:25:27 -07001304void wlan_hdd_set_mcc_latency(struct hdd_adapter *adapter, int set_value)
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001305{
1306 uint32_t concurrent_state;
Jeff Johnson18767622017-08-28 11:46:50 -07001307 struct hdd_context *hdd_ctx;
Archana Ramachandranb8c04f92017-03-17 20:05:47 -07001308
1309 if (!adapter) {
1310 hdd_err("Invalid adapter");
1311 return;
1312 }
1313
1314 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1315 if (hdd_ctx == NULL) {
1316 hdd_err("HDD context is null");
1317 return;
1318 }
1319
1320 concurrent_state = policy_mgr_get_concurrency_mode(
1321 hdd_ctx->hdd_psoc);
1322 /**
1323 * Check if concurrency mode is active.
1324 * Need to modify this code to support MCC modes other than STA/P2P
1325 */
1326 if ((concurrent_state ==
1327 (QDF_STA_MASK | QDF_P2P_CLIENT_MASK)) ||
1328 (concurrent_state == (QDF_STA_MASK | QDF_P2P_GO_MASK))) {
1329 hdd_info("STA & P2P are both enabled");
1330 /*
1331 * The channel number and latency are formatted in
1332 * a bit vector then passed on to WMA layer.
1333 * +**********************************************+
1334 * |bits 31-16 | bits 15-8 | bits 7-0 |
1335 * | Unused | latency - Chan. 1 | channel no. |
1336 * +**********************************************+
1337 */
1338 set_value = set_first_connection_operating_channel(
1339 hdd_ctx, set_value, adapter->device_mode);
1340
1341 wlan_hdd_send_mcc_latency(adapter, set_value);
1342 } else {
1343 hdd_info("MCC is not active. Exit w/o setting latency");
1344 }
1345}