xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: wlan_hdd_p2p.c
22  *
23  * WLAN Host Device Driver implementation for P2P commands interface
24  */
25 
26 #include "osif_sync.h"
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"
35 #include "qdf_trace.h"
36 #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"
42 #include "qdf_types.h"
43 #include "qdf_trace.h"
44 #include "cds_sched.h"
45 #include "wlan_policy_mgr_api.h"
46 #include "cds_utils.h"
47 #include "wlan_p2p_public_struct.h"
48 #include "wlan_p2p_ucfg_api.h"
49 #include "wlan_cfg80211_p2p.h"
50 #include "wlan_p2p_cfg_api.h"
51 #include "wlan_policy_mgr_ucfg.h"
52 #include "nan_ucfg_api.h"
53 #include "wlan_pkt_capture_ucfg_api.h"
54 #include "wlan_hdd_object_manager.h"
55 #include "wlan_hdd_pre_cac.h"
56 #include "wlan_pre_cac_ucfg_api.h"
57 #include "wlan_dp_ucfg_api.h"
58 #include "wlan_psoc_mlme_ucfg_api.h"
59 #include "os_if_dp_local_pkt_capture.h"
60 
61 /* Ms to Time Unit Micro Sec */
62 #define MS_TO_TU_MUS(x)   ((x) * 1024)
63 #define MAX_MUS_VAL       (INT_MAX / 1024)
64 
65 /* Clean up RoC context at hdd_stop_adapter*/
66 void
wlan_hdd_cleanup_remain_on_channel_ctx(struct wlan_hdd_link_info * link_info)67 wlan_hdd_cleanup_remain_on_channel_ctx(struct wlan_hdd_link_info *link_info)
68 {
69 	struct wlan_objmgr_vdev *vdev;
70 
71 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_P2P_ID);
72 	if (!vdev)
73 		return;
74 
75 	ucfg_p2p_cleanup_roc_by_vdev(vdev);
76 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID);
77 }
78 
wlan_hdd_cleanup_actionframe(struct wlan_hdd_link_info * link_info)79 void wlan_hdd_cleanup_actionframe(struct wlan_hdd_link_info *link_info)
80 {
81 	struct wlan_objmgr_vdev *vdev;
82 
83 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_P2P_ID);
84 	if (!vdev)
85 		return;
86 	ucfg_p2p_cleanup_tx_by_vdev(vdev);
87 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID);
88 }
89 
__wlan_hdd_cfg80211_remain_on_channel(struct wiphy * wiphy,struct wireless_dev * wdev,struct ieee80211_channel * chan,unsigned int duration,u64 * cookie)90 static int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
91 						 struct wireless_dev *wdev,
92 						 struct ieee80211_channel *chan,
93 						 unsigned int duration,
94 						 u64 *cookie)
95 {
96 	struct net_device *dev = wdev->netdev;
97 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
98 	struct hdd_context *hdd_ctx;
99 	struct wlan_objmgr_vdev *vdev;
100 	QDF_STATUS status;
101 	int ret;
102 
103 	hdd_enter();
104 
105 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
106 	ret = wlan_hdd_validate_context(hdd_ctx);
107 	if (0 != ret)
108 		return ret;
109 
110 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
111 		hdd_err("Command not allowed in FTM mode");
112 		return -EINVAL;
113 	}
114 
115 	wlan_hdd_lpc_handle_concurrency(hdd_ctx, false);
116 	if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) &&
117 	    !hdd_lpc_is_work_scheduled(hdd_ctx))
118 		return -EINVAL;
119 
120 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
121 		return -EINVAL;
122 
123 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_P2P_ID);
124 	if (!vdev) {
125 		hdd_err("vdev is NULL");
126 		return -EINVAL;
127 	}
128 
129 	if (!wlan_is_scan_allowed(vdev)) {
130 		wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_P2P_ID);
131 		return -EBUSY;
132 	}
133 
134 	/* Disable NAN Discovery if enabled */
135 	ucfg_nan_disable_concurrency(hdd_ctx->psoc);
136 
137 	status = wlan_cfg80211_roc(vdev, chan, duration, cookie);
138 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID);
139 	hdd_debug("remain on channel request, status:%d, cookie:0x%llx",
140 		  status, *cookie);
141 
142 	return qdf_status_to_os_return(status);
143 }
144 
wlan_hdd_cfg80211_remain_on_channel(struct wiphy * wiphy,struct wireless_dev * wdev,struct ieee80211_channel * chan,unsigned int duration,u64 * cookie)145 int wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
146 					struct wireless_dev *wdev,
147 					struct ieee80211_channel *chan,
148 					unsigned int duration, u64 *cookie)
149 {
150 	int errno;
151 	struct osif_vdev_sync *vdev_sync;
152 
153 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
154 	if (errno)
155 		return errno;
156 
157 	errno = __wlan_hdd_cfg80211_remain_on_channel(wiphy, wdev, chan,
158 						      duration, cookie);
159 
160 	osif_vdev_sync_op_stop(vdev_sync);
161 
162 	return errno;
163 }
164 
165 static int
__wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy * wiphy,struct wireless_dev * wdev,u64 cookie)166 __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
167 					     struct wireless_dev *wdev,
168 					     u64 cookie)
169 {
170 	QDF_STATUS status;
171 	struct net_device *dev = wdev->netdev;
172 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
173 	struct wlan_objmgr_vdev *vdev;
174 
175 	hdd_enter();
176 
177 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
178 		hdd_err("Command not allowed in FTM mode");
179 		return -EINVAL;
180 	}
181 
182 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
183 		return -EINVAL;
184 
185 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_P2P_ID);
186 	if (!vdev) {
187 		hdd_err("vdev is NULL");
188 		return -EINVAL;
189 	}
190 
191 	status = wlan_cfg80211_cancel_roc(vdev, cookie);
192 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID);
193 
194 	hdd_debug("cancel remain on channel, status:%d", status);
195 
196 	return 0;
197 }
198 
wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy * wiphy,struct wireless_dev * wdev,u64 cookie)199 int wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
200 					       struct wireless_dev *wdev,
201 					       u64 cookie)
202 {
203 	int errno;
204 	struct osif_vdev_sync *vdev_sync;
205 
206 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
207 	if (errno)
208 		return errno;
209 
210 	errno = __wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, wdev,
211 							     cookie);
212 
213 	osif_vdev_sync_op_stop(vdev_sync);
214 
215 	return errno;
216 }
217 
218 #define WLAN_AUTH_FRAME_MIN_LEN 2
__wlan_hdd_mgmt_tx(struct wiphy * wiphy,struct wireless_dev * wdev,struct ieee80211_channel * chan,bool offchan,unsigned int wait,const u8 * buf,size_t len,bool no_cck,bool dont_wait_for_ack,u64 * cookie)219 static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
220 			      struct ieee80211_channel *chan, bool offchan,
221 			      unsigned int wait,
222 			      const u8 *buf, size_t len, bool no_cck,
223 			      bool dont_wait_for_ack, u64 *cookie)
224 {
225 	QDF_STATUS status;
226 	struct net_device *dev = wdev->netdev;
227 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
228 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
229 	struct wlan_objmgr_vdev *vdev;
230 	uint8_t type, sub_type;
231 	uint16_t auth_algo;
232 	QDF_STATUS qdf_status;
233 	int ret;
234 	uint32_t assoc_resp_len, ft_info_len = 0;
235 	const uint8_t  *assoc_resp;
236 	void *ft_info;
237 	struct hdd_ap_ctx *ap_ctx;
238 
239 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
240 		hdd_err("Command not allowed in FTM mode");
241 		return -EINVAL;
242 	}
243 
244 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
245 		return -EINVAL;
246 
247 	ret = wlan_hdd_validate_context(hdd_ctx);
248 	if (ret)
249 		return ret;
250 
251 	type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
252 	sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
253 	hdd_debug("type %d, sub_type %d", type, sub_type);
254 
255 	/* When frame to be transmitted is auth mgmt, then trigger
256 	 * sme_send_mgmt_tx to send auth frame without need for policy manager.
257 	 * Where as wlan_cfg80211_mgmt_tx requires roc and requires approval
258 	 * from policy manager.
259 	 */
260 	if ((adapter->device_mode == QDF_STA_MODE ||
261 	     adapter->device_mode == QDF_SAP_MODE ||
262 	     adapter->device_mode == QDF_P2P_CLIENT_MODE ||
263 	     adapter->device_mode == QDF_P2P_GO_MODE ||
264 	     adapter->device_mode == QDF_NAN_DISC_MODE) &&
265 	    (type == SIR_MAC_MGMT_FRAME &&
266 	    sub_type == SIR_MAC_MGMT_AUTH)) {
267 		/* Request ROC for PASN authentication frame */
268 		if (len > (sizeof(struct wlan_frame_hdr) +
269 			   WLAN_AUTH_FRAME_MIN_LEN)) {
270 			auth_algo =
271 				*(uint16_t *)(buf +
272 					      sizeof(struct wlan_frame_hdr));
273 			if (auth_algo == eSIR_AUTH_TYPE_PASN)
274 				goto off_chan_tx;
275 			if ((auth_algo == eSIR_FT_AUTH) &&
276 			    (adapter->device_mode == QDF_SAP_MODE ||
277 			     adapter->device_mode == QDF_P2P_GO_MODE)) {
278 				ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
279 				ap_ctx->during_auth_offload = false;
280 			}
281 		}
282 
283 		qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_SME,
284 			   TRACE_CODE_HDD_SEND_MGMT_TX,
285 			   adapter->deflink->vdev_id, 0);
286 
287 		qdf_status = sme_send_mgmt_tx(hdd_ctx->mac_handle,
288 					      adapter->deflink->vdev_id,
289 					      buf, len);
290 
291 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
292 			return qdf_status_to_os_return(qdf_status);
293 		else
294 			return -EINVAL;
295 	}
296 	/* Only when SAP working on Fast BSS transition mode. Driver offload
297 	 * (re)assoc request to hostapd. Here driver receive (re)assoc response
298 	 * frame from hostapd.
299 	 */
300 	if ((adapter->device_mode == QDF_SAP_MODE ||
301 	     adapter->device_mode == QDF_P2P_GO_MODE) &&
302 	    (type == SIR_MAC_MGMT_FRAME) &&
303 	    (sub_type == SIR_MAC_MGMT_ASSOC_RSP ||
304 	     sub_type == SIR_MAC_MGMT_REASSOC_RSP)) {
305 		assoc_resp = &((struct ieee80211_mgmt *)buf)->u.assoc_resp.variable[0];
306 		assoc_resp_len = len - WLAN_ASSOC_RSP_IES_OFFSET
307 			   - sizeof(struct wlan_frame_hdr);
308 		if (!wlan_get_ie_ptr_from_eid(DOT11F_EID_FTINFO,
309 					      assoc_resp, assoc_resp_len)) {
310 			hdd_debug("No FT info in Assoc rsp, send it directly");
311 			goto off_chan_tx;
312 		}
313 		ft_info = hdd_filter_ft_info(assoc_resp, len, &ft_info_len);
314 		if (!ft_info || !ft_info_len)
315 			return -EINVAL;
316 		hdd_debug("get ft_info_len from Assoc rsp :%d", ft_info_len);
317 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
318 		qdf_status = wlansap_update_ft_info(ap_ctx->sap_context,
319 						    ((struct ieee80211_mgmt *)buf)->da,
320 						    ft_info, ft_info_len, 0);
321 		qdf_mem_free(ft_info);
322 
323 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
324 			return qdf_status_to_os_return(qdf_status);
325 		else
326 			return -EINVAL;
327 	}
328 
329 off_chan_tx:
330 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_P2P_ID);
331 	if (!vdev) {
332 		hdd_err("vdev is NULL");
333 		return -EINVAL;
334 	}
335 
336 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_OS_IF,
337 		   TRACE_CODE_HDD_SEND_MGMT_TX,
338 		   wlan_vdev_get_id(vdev), 0);
339 
340 	status = wlan_cfg80211_mgmt_tx(vdev, chan, offchan, wait, buf,
341 				       len, no_cck, dont_wait_for_ack, cookie);
342 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID);
343 	hdd_debug("device_mode:%d type:%d sub_type:%d chan:%d wait:%d offchan:%d do_not_wait_ack:%d mgmt tx, status:%d, cookie:0x%llx",
344 		  adapter->device_mode, type, sub_type,
345 		  chan ? chan->center_freq : 0, wait, offchan,
346 		  dont_wait_for_ack, status, *cookie);
347 
348 	return 0;
349 }
350 
351 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
wlan_hdd_mgmt_tx(struct wiphy * wiphy,struct wireless_dev * wdev,struct cfg80211_mgmt_tx_params * params,u64 * cookie)352 int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
353 		     struct cfg80211_mgmt_tx_params *params, u64 *cookie)
354 #else
355 int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
356 		     struct ieee80211_channel *chan, bool offchan,
357 		     unsigned int wait,
358 		     const u8 *buf, size_t len, bool no_cck,
359 		     bool dont_wait_for_ack, u64 *cookie)
360 #endif /* LINUX_VERSION_CODE */
361 {
362 	int errno;
363 	struct osif_vdev_sync *vdev_sync;
364 
365 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
366 	if (errno)
367 		return errno;
368 
369 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
370 	errno = __wlan_hdd_mgmt_tx(wiphy, wdev, params->chan, params->offchan,
371 				   params->wait, params->buf, params->len,
372 				   params->no_cck, params->dont_wait_for_ack,
373 				   cookie);
374 #else
375 	errno = __wlan_hdd_mgmt_tx(wiphy, wdev, chan, offchan,
376 				   wait, buf, len, no_cck,
377 				   dont_wait_for_ack, cookie);
378 #endif /* LINUX_VERSION_CODE */
379 
380 	osif_vdev_sync_op_stop(vdev_sync);
381 
382 	return errno;
383 }
384 
__wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy * wiphy,struct wireless_dev * wdev,u64 cookie)385 static int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
386 						   struct wireless_dev *wdev,
387 						   u64 cookie)
388 {
389 	QDF_STATUS status;
390 	struct net_device *dev = wdev->netdev;
391 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
392 	struct wlan_objmgr_vdev *vdev;
393 
394 	hdd_enter();
395 
396 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
397 		hdd_err("Command not allowed in FTM mode");
398 		return -EINVAL;
399 	}
400 
401 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
402 		return -EINVAL;
403 
404 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_P2P_ID);
405 	if (!vdev) {
406 		hdd_err("vdev is NULL");
407 		return -EINVAL;
408 	}
409 
410 	status = wlan_cfg80211_mgmt_tx_cancel(vdev, cookie);
411 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID);
412 
413 	hdd_debug("cancel mgmt tx, status:%d", status);
414 
415 	return 0;
416 }
417 
wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy * wiphy,struct wireless_dev * wdev,u64 cookie)418 int wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
419 					  struct wireless_dev *wdev, u64 cookie)
420 {
421 	int errno;
422 	struct osif_vdev_sync *vdev_sync;
423 
424 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
425 	if (errno)
426 		return errno;
427 
428 	errno = __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(wiphy, wdev, cookie);
429 
430 	osif_vdev_sync_op_stop(vdev_sync);
431 
432 	return errno;
433 }
434 
435 /**
436  * hdd_set_p2p_noa() - Handle P2P_SET_NOA command
437  * @dev: Pointer to net device structure
438  * @command: Pointer to command
439  *
440  * This function is called from hdd_hostapd_ioctl function when Driver
441  * get P2P_SET_NOA command from wpa_supplicant using private ioctl
442  *
443  * This function will construct the NoA Struct According to P2P Power
444  * save Option and Pass it to SME layer
445  *
446  * Return: 0 on success, negative errno if error
447  */
448 
hdd_set_p2p_noa(struct net_device * dev,uint8_t * command)449 int hdd_set_p2p_noa(struct net_device *dev, uint8_t *command)
450 {
451 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
452 	struct p2p_ps_config noa = {0};
453 	int count, duration, interval, start = 0;
454 	char *param;
455 	int ret;
456 
457 	param = strnchr(command, strlen(command), ' ');
458 	if (!param) {
459 		hdd_err("strnchr failed to find delimiter");
460 		return -EINVAL;
461 	}
462 	param++;
463 	ret = sscanf(param, "%d %d %d %d", &count, &start, &duration,
464 		     &interval);
465 	if (ret < 3) {
466 		hdd_err("P2P_SET GO noa: fail to read params, ret=%d",
467 			ret);
468 		return -EINVAL;
469 	}
470 
471 	if (ret == 3)
472 		interval = 100;
473 
474 	if (start < 0 || count < 0 || interval < 0 || duration < 0 ||
475 	    start > MAX_MUS_VAL || interval > MAX_MUS_VAL ||
476 	    duration > MAX_MUS_VAL) {
477 		hdd_err("Invalid NOA parameters");
478 		return -EINVAL;
479 	}
480 	hdd_debug("P2P_SET GO noa: count=%d interval=%d duration=%d start=%d",
481 		  count, interval, duration, start);
482 	duration = MS_TO_TU_MUS(duration);
483 	interval = MS_TO_TU_MUS(interval);
484 	/* PS Selection
485 	 * Periodic noa (2)
486 	 * Single NOA   (4)
487 	 */
488 	noa.opp_ps = 0;
489 	noa.ct_window = 0;
490 	if (count == 1) {
491 		if (duration > interval)
492 			duration = interval;
493 		noa.duration = 0;
494 		noa.single_noa_duration = duration;
495 		noa.ps_selection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
496 	} else {
497 		if (count && (duration >= interval)) {
498 			hdd_err("Duration should be less than interval");
499 			return -EINVAL;
500 		}
501 		noa.duration = duration;
502 		noa.single_noa_duration = 0;
503 		noa.ps_selection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
504 	}
505 
506 	noa.start = start;
507 	noa.interval = interval;
508 	noa.count = count;
509 	noa.vdev_id = adapter->deflink->vdev_id;
510 
511 	hdd_debug("P2P_PS_ATTR:opp ps %d ct window %d count %d interval %d "
512 		  "duration %d start %d single noa duration %d "
513 		  "ps selection %x", noa.opp_ps, noa.ct_window, noa.count,
514 		  noa.interval, noa.duration, noa.start,
515 		  noa.single_noa_duration, noa.ps_selection);
516 
517 	return wlan_hdd_set_power_save(adapter, &noa);
518 }
519 
520 /**
521  * hdd_set_p2p_opps() - Handle P2P_SET_PS command
522  * @dev: Pointer to net device structure
523  * @command: Pointer to command
524  *
525  * This function is called from hdd_hostapd_ioctl function when Driver
526  * get P2P_SET_PS command from wpa_supplicant using private ioctl.
527  *
528  * This function will construct the NoA Struct According to P2P Power
529  * save Option and Pass it to SME layer
530  *
531  * Return: 0 on success, negative errno if error
532  */
533 
hdd_set_p2p_opps(struct net_device * dev,uint8_t * command)534 int hdd_set_p2p_opps(struct net_device *dev, uint8_t *command)
535 {
536 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
537 	struct p2p_ps_config noa = {0};
538 	char *param;
539 	int legacy_ps, opp_ps, ctwindow;
540 	int ret;
541 
542 	param = strnchr(command, strlen(command), ' ');
543 	if (!param) {
544 		hdd_err("strnchr failed to find delimiter");
545 		return -EINVAL;
546 	}
547 	param++;
548 	ret = sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
549 	if (ret != 3) {
550 		hdd_err("P2P_SET GO PS: fail to read params, ret=%d", ret);
551 		return -EINVAL;
552 	}
553 
554 	if ((opp_ps != -1) && (opp_ps != 0) && (opp_ps != 1)) {
555 		hdd_err("Invalid opp_ps value:%d", opp_ps);
556 		return -EINVAL;
557 	}
558 
559 	/* P2P spec: 3.3.2 Power Management and discovery:
560 	 *     CTWindow should be at least 10 TU.
561 	 * P2P spec: Table 27 - CTWindow and OppPS Parameters field format:
562 	 *     CTWindow and OppPS Parameters together is 8 bits.
563 	 *     CTWindow uses 7 bits (0-6, Bit 7 is for OppPS)
564 	 * 0 indicates that there shall be no CTWindow
565 	 */
566 	if ((ctwindow != -1) && (ctwindow != 0) &&
567 	    (!((ctwindow >= 10) && (ctwindow <= 127)))) {
568 		hdd_err("Invalid CT window value:%d", ctwindow);
569 		return -EINVAL;
570 	}
571 
572 	hdd_debug("P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d",
573 		  legacy_ps, opp_ps, ctwindow);
574 
575 	/* PS Selection
576 	 * Opportunistic Power Save (1)
577 	 */
578 
579 	/* From wpa_cli user need to use separate command to set ct_window
580 	 * and Opps when user want to set ct_window during that time other
581 	 * parameters values are coming from wpa_supplicant as -1.
582 	 * Example : User want to set ct_window with 30 then wpa_cli command :
583 	 * P2P_SET ctwindow 30
584 	 * Command Received at hdd_hostapd_ioctl is as below:
585 	 * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
586 	 *
587 	 * e.g., 1: P2P_SET_PS 1 1 30
588 	 * Driver sets the Opps and CTwindow as 30 and send it to FW.
589 	 * e.g., 2: P2P_SET_PS 1 -1 15
590 	 * Driver caches the CTwindow value but not send the command to FW.
591 	 * e.g., 3: P2P_SET_PS 1 1 -1
592 	 * Driver sends the command to FW with Opps enabled and CT window as
593 	 * 15 (last cached CTWindow value).
594 	 * (or) : P2P_SET_PS 1 1 20
595 	 * Driver sends the command to FW with opps enabled and CT window
596 	 * as 20.
597 	 *
598 	 * legacy_ps param remains unused until required in the future.
599 	 */
600 	if (ctwindow != -1)
601 		adapter->ctw = ctwindow;
602 
603 	/* Send command to FW when OppPS is either enabled(1)/disabled(0) */
604 	if (opp_ps != -1) {
605 		adapter->ops = opp_ps;
606 		noa.opp_ps = adapter->ops;
607 		noa.ct_window = adapter->ctw;
608 		noa.duration = 0;
609 		noa.single_noa_duration = 0;
610 		noa.interval = 0;
611 		noa.count = 0;
612 		noa.ps_selection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
613 		noa.vdev_id = adapter->deflink->vdev_id;
614 
615 		hdd_debug("P2P_PS_ATTR: opp ps %d ct window %d duration %d interval %d count %d single noa duration %d ps selection %x",
616 			noa.opp_ps, noa.ct_window,
617 			noa.duration, noa.interval, noa.count,
618 			noa.single_noa_duration,
619 			noa.ps_selection);
620 
621 		wlan_hdd_set_power_save(adapter, &noa);
622 	}
623 
624 	return 0;
625 }
626 
hdd_set_p2p_ps(struct net_device * dev,void * msgData)627 int hdd_set_p2p_ps(struct net_device *dev, void *msgData)
628 {
629 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
630 	struct p2p_ps_config noa = {0};
631 	struct p2p_app_set_ps *pappnoa = (struct p2p_app_set_ps *) msgData;
632 
633 	noa.opp_ps = pappnoa->opp_ps;
634 	noa.ct_window = pappnoa->ct_window;
635 	noa.duration = pappnoa->duration;
636 	noa.interval = pappnoa->interval;
637 	noa.count = pappnoa->count;
638 	noa.single_noa_duration = pappnoa->single_noa_duration;
639 	noa.ps_selection = pappnoa->ps_selection;
640 	noa.vdev_id = adapter->deflink->vdev_id;
641 
642 	return wlan_hdd_set_power_save(adapter, &noa);
643 }
644 
hdd_allow_new_intf(struct hdd_context * hdd_ctx,enum QDF_OPMODE mode)645 bool hdd_allow_new_intf(struct hdd_context *hdd_ctx,
646 			enum QDF_OPMODE mode)
647 {
648 	struct hdd_adapter *adapter = NULL;
649 	struct hdd_adapter *next_adapter = NULL;
650 	uint8_t num_active_adapter = 0;
651 
652 	if (mode != QDF_SAP_MODE)
653 		return true;
654 
655 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
656 					   NET_DEV_HOLD_ALLOW_NEW_INTF) {
657 		if (hdd_is_interface_up(adapter) &&
658 		    adapter->device_mode == mode)
659 			num_active_adapter++;
660 
661 		hdd_adapter_dev_put_debug(adapter,
662 					  NET_DEV_HOLD_ALLOW_NEW_INTF);
663 	}
664 
665 	if (num_active_adapter >= QDF_MAX_NO_OF_SAP_MODE)
666 		hdd_err("sap max allowed intf %d, curr %d",
667 			QDF_MAX_NO_OF_SAP_MODE, num_active_adapter);
668 
669 	return num_active_adapter < QDF_MAX_NO_OF_SAP_MODE;
670 }
671 
672 /**
673  * __wlan_hdd_add_virtual_intf() - Add virtual interface
674  * @wiphy: wiphy pointer
675  * @name: User-visible name of the interface
676  * @name_assign_type: the name of assign type of the netdev
677  * @type: (virtual) interface types
678  * @flags: monitor configuration flags
679  * @params: virtual interface parameters (not used)
680  *
681  * Return: the pointer of wireless dev, otherwise ERR_PTR.
682  */
683 static
__wlan_hdd_add_virtual_intf(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,enum nl80211_iftype type,u32 * flags,struct vif_params * params)684 struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
685 						 const char *name,
686 						 unsigned char name_assign_type,
687 						 enum nl80211_iftype type,
688 						 u32 *flags,
689 						 struct vif_params *params)
690 {
691 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
692 	struct hdd_adapter *adapter = NULL;
693 	bool p2p_dev_addr_admin = false;
694 	enum QDF_OPMODE mode;
695 	QDF_STATUS status;
696 	struct wlan_objmgr_vdev *vdev;
697 	int ret;
698 	struct hdd_adapter_create_param create_params = {0};
699 	uint8_t *device_address = NULL;
700 
701 	hdd_enter();
702 
703 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
704 		hdd_err("Command not allowed in FTM mode");
705 		return ERR_PTR(-EINVAL);
706 	}
707 
708 	if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) {
709 		hdd_err("Concurrency not allowed with standalone monitor mode");
710 		return ERR_PTR(-EINVAL);
711 	}
712 
713 	ret = wlan_hdd_validate_context(hdd_ctx);
714 	if (ret)
715 		return ERR_PTR(ret);
716 
717 	status = hdd_nl_to_qdf_iface_type(type, &mode);
718 	if (QDF_IS_STATUS_ERROR(status))
719 		return ERR_PTR(qdf_status_to_os_return(status));
720 
721 	if (mode == QDF_MONITOR_MODE &&
722 	    !(QDF_MONITOR_FLAG_OTHER_BSS & *flags) &&
723 	    !os_if_lpc_mon_intf_creation_allowed(hdd_ctx->psoc))
724 		return ERR_PTR(-EOPNOTSUPP);
725 
726 	wlan_hdd_lpc_handle_concurrency(hdd_ctx, true);
727 
728 	if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) &&
729 	    !hdd_lpc_is_work_scheduled(hdd_ctx))
730 		return ERR_PTR(-EINVAL);
731 
732 	if (wlan_hdd_is_mon_concurrency())
733 		return ERR_PTR(-EINVAL);
734 
735 	if (!hdd_allow_new_intf(hdd_ctx, mode))
736 		return ERR_PTR(-EOPNOTSUPP);
737 
738 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
739 		   TRACE_CODE_HDD_ADD_VIRTUAL_INTF,
740 		   NO_SESSION, type);
741 
742 	switch (mode) {
743 	case QDF_SAP_MODE:
744 	case QDF_P2P_GO_MODE:
745 	case QDF_P2P_CLIENT_MODE:
746 	case QDF_STA_MODE:
747 	case QDF_MONITOR_MODE:
748 		break;
749 	default:
750 		mode = QDF_STA_MODE;
751 		break;
752 	}
753 
754 	create_params.is_add_virtual_iface = 1;
755 
756 	adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
757 	if (adapter && !wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) {
758 		vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
759 						   WLAN_OSIF_P2P_ID);
760 		if (vdev) {
761 			if (ucfg_scan_get_vdev_status(vdev) !=
762 							SCAN_NOT_IN_PROGRESS) {
763 				wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
764 						adapter->deflink->vdev_id,
765 						INVALID_SCAN_ID, false);
766 			}
767 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_P2P_ID);
768 		} else {
769 			hdd_err("vdev is NULL");
770 		}
771 	}
772 
773 	adapter = NULL;
774 	if (type == NL80211_IFTYPE_MONITOR) {
775 		bool is_rx_mon = QDF_MONITOR_FLAG_OTHER_BSS & *flags;
776 
777 		/*
778 		 * if QDF_MONITOR_FLAG_OTHER_BSS bit is set in monitor flags
779 		 * driver will assume current mode as STA + Monitor Mode.
780 		 * So if QDF_MONITOR_FLAG_OTHER_BSS bit is set in monitor
781 		 * interface flag STA+MON concurrency is not supported
782 		 * reject the request.
783 		 **/
784 		if ((ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc) &&
785 		     !is_rx_mon) ||
786 		    (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) &&
787 		     is_rx_mon) ||
788 		    ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
789 						PACKET_CAPTURE_MODE_DISABLE) {
790 			ret = wlan_hdd_add_monitor_check(hdd_ctx,
791 							 &adapter, name, true,
792 							 name_assign_type,
793 							 is_rx_mon);
794 			if (ret)
795 				return ERR_PTR(-EINVAL);
796 
797 			ucfg_dp_set_mon_conf_flags(hdd_ctx->psoc, *flags);
798 
799 			if (adapter) {
800 				hdd_exit();
801 				return adapter->dev->ieee80211_ptr;
802 			}
803 		} else {
804 			hdd_err("Adding monitor interface not supported");
805 			return ERR_PTR(-EINVAL);
806 		}
807 	}
808 
809 	adapter = NULL;
810 	cfg_p2p_get_device_addr_admin(hdd_ctx->psoc, &p2p_dev_addr_admin);
811 	if (p2p_dev_addr_admin &&
812 	    (mode == QDF_P2P_GO_MODE || mode == QDF_P2P_CLIENT_MODE)) {
813 		/*
814 		 * Generate the P2P Interface Address. this address must be
815 		 * different from the P2P Device Address.
816 		 */
817 		struct qdf_mac_addr p2p_device_address =
818 						hdd_ctx->p2p_device_address;
819 		p2p_device_address.bytes[4] ^= 0x80;
820 		adapter = hdd_open_adapter(hdd_ctx, mode, name,
821 					   p2p_device_address.bytes,
822 					   name_assign_type, true,
823 					   &create_params);
824 	} else {
825 		if (strnstr(name, "p2p", 3) && mode == QDF_STA_MODE) {
826 			hdd_debug("change mode to p2p device");
827 			mode = QDF_P2P_DEVICE_MODE;
828 		}
829 
830 		device_address = wlan_hdd_get_intf_addr(hdd_ctx, mode);
831 		if (!device_address)
832 			return ERR_PTR(-EINVAL);
833 
834 		adapter = hdd_open_adapter(hdd_ctx, mode, name,
835 					   device_address,
836 					   name_assign_type, true,
837 					   &create_params);
838 		if (!adapter)
839 			wlan_hdd_release_intf_addr(hdd_ctx, device_address);
840 	}
841 
842 	if (!adapter) {
843 		hdd_err("hdd_open_adapter failed with iftype %d", type);
844 		return ERR_PTR(-ENOSPC);
845 	}
846 
847 	adapter->delete_in_progress = false;
848 
849 	/* ensure physical soc is up */
850 	ret = hdd_trigger_psoc_idle_restart(hdd_ctx);
851 	if (ret) {
852 		hdd_err("Failed to start the wlan_modules");
853 		goto close_adapter;
854 	}
855 
856 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
857 	if (vdev) {
858 		ucfg_dp_try_send_rps_ind(vdev);
859 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
860 	}
861 
862 	hdd_exit();
863 
864 	return adapter->dev->ieee80211_ptr;
865 
866 close_adapter:
867 	if (device_address)
868 		wlan_hdd_release_intf_addr(hdd_ctx, device_address);
869 	hdd_close_adapter(hdd_ctx, adapter, true);
870 
871 	return ERR_PTR(-EINVAL);
872 }
873 
874 static struct wireless_dev *
_wlan_hdd_add_virtual_intf(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,enum nl80211_iftype type,u32 * flags,struct vif_params * params)875 _wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
876 			   const char *name,
877 			   unsigned char name_assign_type,
878 			   enum nl80211_iftype type,
879 			   u32 *flags,
880 			   struct vif_params *params)
881 {
882 	struct wireless_dev *wdev;
883 	struct osif_vdev_sync *vdev_sync;
884 	int errno;
885 
886 	errno = osif_vdev_sync_create_and_trans(wiphy_dev(wiphy), &vdev_sync);
887 	if (errno)
888 		return ERR_PTR(errno);
889 
890 	wdev = __wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
891 					   type, flags, params);
892 
893 	if (IS_ERR_OR_NULL(wdev))
894 		goto destroy_sync;
895 
896 	osif_vdev_sync_register(wdev->netdev, vdev_sync);
897 	osif_vdev_sync_trans_stop(vdev_sync);
898 
899 	return wdev;
900 
901 destroy_sync:
902 	osif_vdev_sync_trans_stop(vdev_sync);
903 	osif_vdev_sync_destroy(vdev_sync);
904 
905 	return wdev;
906 }
907 
908 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
wlan_hdd_add_virtual_intf(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,enum nl80211_iftype type,struct vif_params * params)909 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
910 					       const char *name,
911 					       unsigned char name_assign_type,
912 					       enum nl80211_iftype type,
913 					       struct vif_params *params)
914 {
915 	return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
916 					  type, &params->flags, params);
917 }
918 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || defined(WITH_BACKPORTS)
wlan_hdd_add_virtual_intf(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,enum nl80211_iftype type,u32 * flags,struct vif_params * params)919 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
920 					       const char *name,
921 					       unsigned char name_assign_type,
922 					       enum nl80211_iftype type,
923 					       u32 *flags,
924 					       struct vif_params *params)
925 {
926 	return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
927 					  type, flags, params);
928 }
929 #else
wlan_hdd_add_virtual_intf(struct wiphy * wiphy,const char * name,enum nl80211_iftype type,u32 * flags,struct vif_params * params)930 struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
931 					       const char *name,
932 					       enum nl80211_iftype type,
933 					       u32 *flags,
934 					       struct vif_params *params)
935 {
936 	return _wlan_hdd_add_virtual_intf(wiphy, name, name_assign_type,
937 					  type, flags, params);
938 }
939 #endif
940 
941 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
942 	!defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
943 /**
944  * hdd_deinit_mlo_interfaces() - De-initialize link adapters
945  * @hdd_ctx: Pointer to hdd context
946  * @adapter: Pointer to adapter
947  * @rtnl_held: rtnl lock
948  *
949  * Return: None
950  */
hdd_deinit_mlo_interfaces(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,bool rtnl_held)951 static void hdd_deinit_mlo_interfaces(struct hdd_context *hdd_ctx,
952 				      struct hdd_adapter *adapter,
953 				      bool rtnl_held)
954 {
955 	int i;
956 	struct hdd_mlo_adapter_info *mlo_adapter_info;
957 	struct hdd_adapter *link_adapter;
958 
959 	mlo_adapter_info = &adapter->mlo_adapter_info;
960 	for (i = 0; i < WLAN_MAX_MLD; i++) {
961 		link_adapter = mlo_adapter_info->link_adapter[i];
962 		if (!link_adapter)
963 			continue;
964 		hdd_deinit_adapter(hdd_ctx, link_adapter, rtnl_held);
965 	}
966 }
967 #else
968 static inline
hdd_deinit_mlo_interfaces(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter,bool rtnl_held)969 void hdd_deinit_mlo_interfaces(struct hdd_context *hdd_ctx,
970 			       struct hdd_adapter *adapter,
971 			       bool rtnl_held)
972 {
973 }
974 #endif
975 
hdd_clean_up_interface(struct hdd_context * hdd_ctx,struct hdd_adapter * adapter)976 void hdd_clean_up_interface(struct hdd_context *hdd_ctx,
977 			    struct hdd_adapter *adapter)
978 {
979 	wlan_hdd_release_intf_addr(hdd_ctx,
980 				   adapter->mac_addr.bytes);
981 	hdd_stop_adapter(hdd_ctx, adapter);
982 	if (hdd_adapter_is_ml_adapter(adapter)) {
983 		hdd_deinit_mlo_interfaces(hdd_ctx, adapter, true);
984 		hdd_wlan_unregister_mlo_interfaces(adapter, true);
985 	}
986 	hdd_deinit_adapter(hdd_ctx, adapter, true);
987 	hdd_close_adapter(hdd_ctx, adapter, true);
988 }
989 
__wlan_hdd_del_virtual_intf(struct wiphy * wiphy,struct wireless_dev * wdev)990 int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
991 {
992 	struct net_device *dev = wdev->netdev;
993 	struct hdd_context *hdd_ctx = (struct hdd_context *) wiphy_priv(wiphy);
994 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
995 	int errno;
996 
997 	hdd_enter();
998 
999 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1000 		hdd_err("Command not allowed in FTM mode");
1001 		return -EINVAL;
1002 	}
1003 
1004 	/*
1005 	 * Clear SOFTAP_INIT_DONE flag to mark SAP unload, so that we do
1006 	 * not restart SAP after SSR as SAP is already stopped from user space.
1007 	 */
1008 	clear_bit(SOFTAP_INIT_DONE, &adapter->deflink->link_flags);
1009 
1010 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
1011 		   TRACE_CODE_HDD_DEL_VIRTUAL_INTF,
1012 		   adapter->deflink->vdev_id, adapter->device_mode);
1013 
1014 	hdd_debug("Device_mode %s(%d)",
1015 		  qdf_opmode_str(adapter->device_mode), adapter->device_mode);
1016 
1017 	errno = wlan_hdd_validate_context(hdd_ctx);
1018 	if (errno)
1019 		return errno;
1020 
1021 	/* ensure physical soc is up */
1022 	errno = hdd_trigger_psoc_idle_restart(hdd_ctx);
1023 	if (errno)
1024 		return errno;
1025 
1026 	if (wlan_hdd_is_session_type_monitor(adapter->device_mode))
1027 		ucfg_dp_set_mon_conf_flags(hdd_ctx->psoc, 0);
1028 
1029 	if (adapter->device_mode == QDF_SAP_MODE &&
1030 	    ucfg_pre_cac_is_active(hdd_ctx->psoc)) {
1031 		ucfg_pre_cac_clean_up(hdd_ctx->psoc);
1032 		hdd_clean_up_interface(hdd_ctx, adapter);
1033 	} else if (wlan_hdd_is_session_type_monitor(
1034 					adapter->device_mode) &&
1035 		   ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
1036 						PACKET_CAPTURE_MODE_DISABLE) {
1037 		wlan_hdd_del_monitor(hdd_ctx, adapter, TRUE);
1038 	} else {
1039 		hdd_clean_up_interface(hdd_ctx, adapter);
1040 	}
1041 
1042 	if (!hdd_is_any_interface_open(hdd_ctx))
1043 		hdd_psoc_idle_timer_start(hdd_ctx);
1044 	hdd_exit();
1045 
1046 	return 0;
1047 }
1048 
wlan_hdd_del_virtual_intf(struct wiphy * wiphy,struct wireless_dev * wdev)1049 int wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
1050 {
1051 	int errno;
1052 	struct osif_vdev_sync *vdev_sync;
1053 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
1054 
1055 	adapter->delete_in_progress = true;
1056 	errno = osif_vdev_sync_trans_start_wait(wdev->netdev, &vdev_sync);
1057 	if (errno)
1058 		return errno;
1059 
1060 	osif_vdev_sync_unregister(wdev->netdev);
1061 	osif_vdev_sync_wait_for_ops(vdev_sync);
1062 
1063 	adapter->is_virtual_iface = true;
1064 	errno = __wlan_hdd_del_virtual_intf(wiphy, wdev);
1065 
1066 	osif_vdev_sync_trans_stop(vdev_sync);
1067 	osif_vdev_sync_destroy(vdev_sync);
1068 
1069 	return errno;
1070 }
1071 
1072 /**
1073  * hdd_is_qos_action_frame() - check if frame is QOS action frame
1074  * @pb_frames: frame pointer
1075  * @frame_len: frame length
1076  *
1077  * Return: true if it is QOS action frame else false.
1078  */
1079 static inline bool
hdd_is_qos_action_frame(uint8_t * pb_frames,uint32_t frame_len)1080 hdd_is_qos_action_frame(uint8_t *pb_frames, uint32_t frame_len)
1081 {
1082 	if (frame_len <= WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1) {
1083 		hdd_debug("Not a QOS frame len: %d", frame_len);
1084 		return false;
1085 	}
1086 
1087 	return ((pb_frames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] ==
1088 		 WLAN_HDD_QOS_ACTION_FRAME) &&
1089 		(pb_frames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1] ==
1090 		 WLAN_HDD_QOS_MAP_CONFIGURE));
1091 }
1092 
1093 #if defined(WLAN_FEATURE_SAE) && defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT)
1094 /**
1095  * wlan_hdd_set_rxmgmt_external_auth_flag() - Set the EXTERNAL_AUTH flag
1096  * @nl80211_flag: flags to be sent to nl80211 from enum nl80211_rxmgmt_flags
1097  *
1098  * Set the flag NL80211_RXMGMT_FLAG_EXTERNAL_AUTH if supported.
1099  */
1100 static void
wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags * nl80211_flag)1101 wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag)
1102 {
1103 		*nl80211_flag |= NL80211_RXMGMT_FLAG_EXTERNAL_AUTH;
1104 }
1105 #else
1106 static void
wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags * nl80211_flag)1107 wlan_hdd_set_rxmgmt_external_auth_flag(enum nl80211_rxmgmt_flags *nl80211_flag)
1108 {
1109 }
1110 #endif
1111 
1112 /**
1113  * wlan_hdd_cfg80211_convert_rxmgmt_flags() - Convert RXMGMT value
1114  * @nl80211_flag: Flags to be sent to nl80211 from enum nl80211_rxmgmt_flags
1115  * @flag: flags set by driver(SME/PE) from enum rxmgmt_flags
1116  *
1117  * Convert driver internal RXMGMT flag value to nl80211 defined RXMGMT flag
1118  * Return: void
1119  */
1120 static void
wlan_hdd_cfg80211_convert_rxmgmt_flags(enum rxmgmt_flags flag,enum nl80211_rxmgmt_flags * nl80211_flag)1121 wlan_hdd_cfg80211_convert_rxmgmt_flags(enum rxmgmt_flags flag,
1122 				       enum nl80211_rxmgmt_flags *nl80211_flag)
1123 {
1124 
1125 	if (flag & RXMGMT_FLAG_EXTERNAL_AUTH) {
1126 		wlan_hdd_set_rxmgmt_external_auth_flag(nl80211_flag);
1127 	}
1128 
1129 }
1130 
1131 static void
__hdd_indicate_mgmt_frame_to_user(struct hdd_adapter * adapter,uint32_t frm_len,uint8_t * pb_frames,uint8_t frame_type,uint32_t rx_freq,int8_t rx_rssi,enum rxmgmt_flags rx_flags)1132 __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
1133 				  uint32_t frm_len, uint8_t *pb_frames,
1134 				  uint8_t frame_type, uint32_t rx_freq,
1135 				  int8_t rx_rssi, enum rxmgmt_flags rx_flags)
1136 {
1137 	uint8_t type = 0;
1138 	uint8_t sub_type = 0;
1139 	struct hdd_context *hdd_ctx;
1140 	uint8_t *dest_addr = NULL;
1141 	uint16_t auth_algo;
1142 	enum nl80211_rxmgmt_flags nl80211_flag = 0;
1143 	bool is_pasn_auth_frame = false;
1144 	struct hdd_adapter *assoc_adapter;
1145 	bool eht_capab;
1146 	struct hdd_ap_ctx *ap_ctx;
1147 	struct action_frm_hdr *action_hdr;
1148 	tpSirMacVendorSpecificPublicActionFrameHdr vendor_specific;
1149 
1150 	hdd_debug("Frame Type = %d Frame Length = %d freq = %d",
1151 		  frame_type, frm_len, rx_freq);
1152 
1153 	if (!adapter) {
1154 		hdd_err("adapter is NULL");
1155 		return;
1156 	}
1157 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1158 
1159 	if (!frm_len) {
1160 		hdd_err("Frame Length is Invalid ZERO");
1161 		return;
1162 	}
1163 
1164 	if (!pb_frames) {
1165 		hdd_err("pbFrames is NULL");
1166 		return;
1167 	}
1168 
1169 	type = WLAN_HDD_GET_TYPE_FRM_FC(pb_frames[0]);
1170 	sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(pb_frames[0]);
1171 	if (type == SIR_MAC_MGMT_FRAME &&
1172 	    sub_type == SIR_MAC_MGMT_AUTH &&
1173 	    frm_len > (sizeof(struct wlan_frame_hdr) +
1174 		       WLAN_AUTH_FRAME_MIN_LEN)) {
1175 		auth_algo = *(uint16_t *)(pb_frames +
1176 					  sizeof(struct wlan_frame_hdr));
1177 		if (auth_algo == eSIR_AUTH_TYPE_PASN) {
1178 			is_pasn_auth_frame = true;
1179 		} else if (auth_algo == eSIR_FT_AUTH &&
1180 			   (adapter->device_mode == QDF_SAP_MODE ||
1181 			    adapter->device_mode == QDF_P2P_GO_MODE)) {
1182 			ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
1183 			ap_ctx->during_auth_offload = true;
1184 		}
1185 	}
1186 
1187 	if (type == WLAN_FC0_TYPE_MGMT && sub_type == WLAN_FC0_STYPE_ACTION &&
1188 	    frm_len >= (sizeof(struct wlan_frame_hdr) +
1189 			sizeof(*vendor_specific))) {
1190 		action_hdr = (struct action_frm_hdr *)(pb_frames +
1191 						sizeof(struct wlan_frame_hdr));
1192 		vendor_specific =
1193 			(tpSirMacVendorSpecificPublicActionFrameHdr)action_hdr;
1194 		if (is_nan_oui(vendor_specific->Oui)) {
1195 			adapter = hdd_get_adapter(hdd_ctx, QDF_NAN_DISC_MODE);
1196 			if (!adapter) {
1197 				hdd_err("NAN adapter is null");
1198 				return;
1199 			}
1200 
1201 			goto check_adapter;
1202 		}
1203 	}
1204 
1205 	/* Get adapter from Destination mac address of the frame */
1206 	if (type == SIR_MAC_MGMT_FRAME &&
1207 	    sub_type != SIR_MAC_MGMT_PROBE_REQ && !is_pasn_auth_frame &&
1208 	    !qdf_is_macaddr_broadcast(
1209 	     (struct qdf_mac_addr *)&pb_frames[WLAN_HDD_80211_FRM_DA_OFFSET])) {
1210 		dest_addr = &pb_frames[WLAN_HDD_80211_FRM_DA_OFFSET];
1211 		adapter = hdd_get_adapter_by_macaddr(hdd_ctx, dest_addr);
1212 		if (!adapter)
1213 			adapter = hdd_get_adapter_by_rand_macaddr(hdd_ctx,
1214 								  dest_addr);
1215 		if (!adapter) {
1216 			/*
1217 			 * Under assumption that we don't receive any action
1218 			 * frame with BCST as destination,
1219 			 * we are dropping action frame
1220 			 */
1221 			hdd_err("adapter for action frame is NULL Macaddr = "
1222 				QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(dest_addr));
1223 			hdd_debug("Frame Type = %d Frame Length = %d subType = %d",
1224 				  frame_type, frm_len, sub_type);
1225 			/*
1226 			 * We will receive broadcast management frames
1227 			 * in OCB mode
1228 			 */
1229 			adapter = hdd_get_adapter(hdd_ctx, QDF_OCB_MODE);
1230 			if (!adapter || !qdf_is_macaddr_broadcast(
1231 			    (struct qdf_mac_addr *)dest_addr)) {
1232 				/*
1233 				 * Under assumption that we don't
1234 				 * receive any action frame with BCST
1235 				 * as destination, we are dropping
1236 				 * action frame
1237 				 */
1238 				return;
1239 			}
1240 		}
1241 	}
1242 
1243 check_adapter:
1244 	if (!adapter->dev) {
1245 		hdd_err("adapter->dev is NULL");
1246 		return;
1247 	}
1248 
1249 	if (WLAN_HDD_ADAPTER_MAGIC != adapter->magic) {
1250 		hdd_err("adapter has invalid magic");
1251 		return;
1252 	}
1253 
1254 	/* Channel indicated may be wrong. TODO */
1255 	/* Indicate an action frame. */
1256 
1257 	if (hdd_is_qos_action_frame(pb_frames, frm_len))
1258 		sme_update_dsc_pto_up_mapping(hdd_ctx->mac_handle,
1259 					      adapter->dscp_to_up_map,
1260 					      adapter->deflink->vdev_id);
1261 
1262 	assoc_adapter = adapter;
1263 	ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
1264 	if (hdd_adapter_is_link_adapter(adapter) && eht_capab) {
1265 		hdd_debug("adapter is not ml adapter move to ml adapter");
1266 		assoc_adapter = hdd_adapter_get_mlo_adapter_from_link(adapter);
1267 		if (!assoc_adapter) {
1268 			hdd_err("Assoc adapter is NULL");
1269 			return;
1270 		}
1271 	}
1272 
1273 	/* Indicate Frame Over Normal Interface */
1274 	hdd_debug("Indicate Frame over NL80211 sessionid : %d, idx :%d",
1275 		   assoc_adapter->deflink->vdev_id,
1276 		   assoc_adapter->dev->ifindex);
1277 
1278 	wlan_hdd_cfg80211_convert_rxmgmt_flags(rx_flags, &nl80211_flag);
1279 
1280 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
1281 	cfg80211_rx_mgmt(assoc_adapter->dev->ieee80211_ptr,
1282 			 rx_freq, rx_rssi * 100, pb_frames,
1283 			 frm_len, NL80211_RXMGMT_FLAG_ANSWERED | nl80211_flag);
1284 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
1285 	cfg80211_rx_mgmt(assoc_adapter->dev->ieee80211_ptr,
1286 			 rx_freq, rx_rssi * 100, pb_frames,
1287 			 frm_len, NL80211_RXMGMT_FLAG_ANSWERED,
1288 			 GFP_ATOMIC);
1289 #else
1290 	cfg80211_rx_mgmt(assoc_adapter->dev->ieee80211_ptr, rx_freq,
1291 			 rx_rssi * 100,
1292 			 pb_frames, frm_len, GFP_ATOMIC);
1293 #endif /* LINUX_VERSION_CODE */
1294 }
1295 
hdd_indicate_mgmt_frame_to_user(struct hdd_adapter * adapter,uint32_t frm_len,uint8_t * pb_frames,uint8_t frame_type,uint32_t rx_freq,int8_t rx_rssi,enum rxmgmt_flags rx_flags)1296 void hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
1297 				     uint32_t frm_len, uint8_t *pb_frames,
1298 				     uint8_t frame_type, uint32_t rx_freq,
1299 				     int8_t rx_rssi, enum rxmgmt_flags rx_flags)
1300 {
1301 	int errno;
1302 	struct osif_vdev_sync *vdev_sync;
1303 
1304 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
1305 	if (errno)
1306 		return;
1307 
1308 	__hdd_indicate_mgmt_frame_to_user(adapter, frm_len, pb_frames,
1309 					  frame_type, rx_freq,
1310 					  rx_rssi, rx_flags);
1311 	osif_vdev_sync_op_stop(vdev_sync);
1312 }
1313 
wlan_hdd_set_power_save(struct hdd_adapter * adapter,struct p2p_ps_config * ps_config)1314 int wlan_hdd_set_power_save(struct hdd_adapter *adapter,
1315 	struct p2p_ps_config *ps_config)
1316 {
1317 	struct wlan_objmgr_psoc *psoc;
1318 	struct hdd_context *hdd_ctx;
1319 	QDF_STATUS status;
1320 
1321 	if (!adapter || !ps_config) {
1322 		hdd_err("null param, adapter:%pK, ps_config:%pK",
1323 			adapter, ps_config);
1324 		return -EINVAL;
1325 	}
1326 
1327 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1328 	psoc = hdd_ctx->psoc;
1329 	if (!psoc) {
1330 		hdd_err("psoc is null");
1331 		return -EINVAL;
1332 	}
1333 
1334 	hdd_debug("opp ps:%d, ct window:%d, duration:%d, interval:%d, count:%d start:%d, single noa duration:%d, ps selection:%d, vdev id:%d",
1335 		  ps_config->opp_ps, ps_config->ct_window,
1336 		  ps_config->duration, ps_config->interval,
1337 		  ps_config->count, ps_config->start,
1338 		  ps_config->single_noa_duration,
1339 		  ps_config->ps_selection, ps_config->vdev_id);
1340 
1341 	status = ucfg_p2p_set_ps(psoc, ps_config);
1342 	hdd_debug("p2p set power save, status:%d", status);
1343 
1344 	/* P2P-GO-NOA and TWT do not go hand in hand */
1345 	if (ps_config->duration) {
1346 		hdd_send_twt_role_disable_cmd(hdd_ctx, TWT_RESPONDER);
1347 	} else {
1348 		hdd_send_twt_requestor_enable_cmd(hdd_ctx);
1349 		hdd_send_twt_responder_enable_cmd(hdd_ctx);
1350 	}
1351 
1352 	return qdf_status_to_os_return(status);
1353 }
1354 
1355 /**
1356  * wlan_hdd_update_mcc_p2p_quota() - Function to Update P2P
1357  * quota to FW
1358  * @adapter:            Pointer to HDD adapter
1359  * @is_set:             0-reset, 1-set
1360  *
1361  * This function passes down the value of MAS to UMAC
1362  *
1363  * Return: none
1364  *
1365  */
wlan_hdd_update_mcc_p2p_quota(struct hdd_adapter * adapter,bool is_set)1366 static void wlan_hdd_update_mcc_p2p_quota(struct hdd_adapter *adapter,
1367 					  bool is_set)
1368 {
1369 
1370 	hdd_info("Set/reset P2P quota: %d", is_set);
1371 	if (is_set) {
1372 		if (adapter->device_mode == QDF_STA_MODE)
1373 			wlan_hdd_set_mcc_p2p_quota(adapter,
1374 				100 - HDD_DEFAULT_MCC_P2P_QUOTA
1375 			);
1376 		else if (adapter->device_mode == QDF_P2P_GO_MODE)
1377 			wlan_hdd_go_set_mcc_p2p_quota(adapter,
1378 				HDD_DEFAULT_MCC_P2P_QUOTA);
1379 		else
1380 			wlan_hdd_set_mcc_p2p_quota(adapter,
1381 				HDD_DEFAULT_MCC_P2P_QUOTA);
1382 	} else {
1383 		if (adapter->device_mode == QDF_P2P_GO_MODE)
1384 			wlan_hdd_go_set_mcc_p2p_quota(adapter,
1385 				HDD_RESET_MCC_P2P_QUOTA);
1386 		else
1387 			wlan_hdd_set_mcc_p2p_quota(adapter,
1388 				HDD_RESET_MCC_P2P_QUOTA);
1389 	}
1390 }
1391 
wlan_hdd_set_mas(struct hdd_adapter * adapter,uint8_t mas_value)1392 int32_t wlan_hdd_set_mas(struct hdd_adapter *adapter, uint8_t mas_value)
1393 {
1394 	struct hdd_context *hdd_ctx;
1395 	bool enable_mcc_adaptive_sch = false;
1396 
1397 	if (!adapter) {
1398 		hdd_err("Adapter is NULL");
1399 		return -EINVAL;
1400 	}
1401 
1402 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1403 	if (!hdd_ctx) {
1404 		hdd_err("HDD context is null");
1405 		return -EINVAL;
1406 	}
1407 
1408 	if (mas_value) {
1409 		hdd_info("Miracast is ON. Disable MAS and configure P2P quota");
1410 		ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc,
1411 						     &enable_mcc_adaptive_sch);
1412 		if (enable_mcc_adaptive_sch) {
1413 			ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch(
1414 							hdd_ctx->psoc, false);
1415 
1416 			if (QDF_STATUS_SUCCESS != sme_set_mas(false)) {
1417 				hdd_err("Failed to disable MAS");
1418 				return -EAGAIN;
1419 			}
1420 		}
1421 
1422 		/* Config p2p quota */
1423 		wlan_hdd_update_mcc_p2p_quota(adapter, true);
1424 	} else {
1425 		hdd_info("Miracast is OFF. Enable MAS and reset P2P quota");
1426 		wlan_hdd_update_mcc_p2p_quota(adapter, false);
1427 
1428 		ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc,
1429 						     &enable_mcc_adaptive_sch);
1430 		if (enable_mcc_adaptive_sch) {
1431 			ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch(
1432 							hdd_ctx->psoc, true);
1433 
1434 			if (QDF_STATUS_SUCCESS != sme_set_mas(true)) {
1435 				hdd_err("Failed to enable MAS");
1436 				return -EAGAIN;
1437 			}
1438 		}
1439 	}
1440 
1441 	return 0;
1442 }
1443 
1444 /**
1445  * set_first_connection_operating_channel() - Function to set
1446  * first connection oerating channel
1447  * @hdd_ctx: Hdd context
1448  * @set_value: First connection operating channel
1449  * @dev_mode: Device operating mode
1450  *
1451  * This function is used to set the first adapter operating
1452  * channel
1453  *
1454  * Return: operating channel updated in set value
1455  *
1456  */
set_first_connection_operating_channel(struct hdd_context * hdd_ctx,uint32_t set_value,enum QDF_OPMODE dev_mode)1457 static uint32_t set_first_connection_operating_channel(
1458 		struct hdd_context *hdd_ctx, uint32_t set_value,
1459 		enum QDF_OPMODE dev_mode)
1460 {
1461 	uint8_t operating_channel;
1462 	uint32_t oper_chan_freq;
1463 
1464 	oper_chan_freq = hdd_get_operating_chan_freq(hdd_ctx, dev_mode);
1465 	if (!oper_chan_freq) {
1466 		hdd_err(" First adapter operating channel is invalid");
1467 		return -EINVAL;
1468 	}
1469 	operating_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
1470 						  oper_chan_freq);
1471 
1472 	hdd_info("First connection channel No.:%d and quota:%dms",
1473 		 operating_channel, set_value);
1474 	/* Move the time quota for first channel to bits 15-8 */
1475 	set_value = set_value << 8;
1476 
1477 	/*
1478 	 * Store the channel number of 1st channel at bits 7-0
1479 	 * of the bit vector
1480 	 */
1481 	return set_value | operating_channel;
1482 }
1483 
1484 /**
1485  * set_second_connection_operating_channel() - Function to set
1486  * second connection oerating channel
1487  * @hdd_ctx: Hdd context
1488  * @set_value: Second connection operating channel
1489  * @vdev_id: vdev id
1490  *
1491  * This function is used to set the first adapter operating
1492  * channel
1493  *
1494  * Return: operating channel updated in set value
1495  *
1496  */
set_second_connection_operating_channel(struct hdd_context * hdd_ctx,uint32_t set_value,uint8_t vdev_id)1497 static uint32_t set_second_connection_operating_channel(
1498 		struct hdd_context *hdd_ctx, uint32_t set_value,
1499 		uint8_t vdev_id)
1500 {
1501 	uint8_t operating_channel;
1502 
1503 	operating_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
1504 						  policy_mgr_get_mcc_operating_channel(
1505 						  hdd_ctx->psoc, vdev_id));
1506 
1507 	if (operating_channel == 0) {
1508 		hdd_err("Second adapter operating channel is invalid");
1509 		return -EINVAL;
1510 	}
1511 
1512 	hdd_info("Second connection channel No.:%d and quota:%dms",
1513 			operating_channel, set_value);
1514 	/*
1515 	 * Now move the time quota and channel number of the
1516 	 * 1st adapter to bits 23-16 and bits 15-8 of the bit
1517 	 * vector, respectively.
1518 	 */
1519 	set_value = set_value << 8;
1520 
1521 	/*
1522 	 * Set the channel number for 2nd MCC vdev at bits
1523 	 * 7-0 of set_value
1524 	 */
1525 	return set_value | operating_channel;
1526 }
1527 
1528 /**
1529  * wlan_hdd_set_mcc_p2p_quota() - Function to set quota for P2P
1530  * @adapter: HDD adapter
1531  * @set_value: Quota value for the interface
1532  *
1533  * This function is used to set the quota for P2P cases
1534  *
1535  * Return: Configuration message posting status, SUCCESS or Fail
1536  *
1537  */
wlan_hdd_set_mcc_p2p_quota(struct hdd_adapter * adapter,uint32_t set_value)1538 int wlan_hdd_set_mcc_p2p_quota(struct hdd_adapter *adapter,
1539 			       uint32_t set_value)
1540 {
1541 	int32_t ret = 0;
1542 	uint32_t concurrent_state;
1543 	struct hdd_context *hdd_ctx;
1544 	uint32_t sta_cli_bit_mask = QDF_STA_MASK | QDF_P2P_CLIENT_MASK;
1545 	uint32_t sta_go_bit_mask = QDF_STA_MASK | QDF_P2P_GO_MASK;
1546 
1547 	if (!adapter) {
1548 		hdd_err("Invalid adapter");
1549 		return -EFAULT;
1550 	}
1551 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1552 	if (!hdd_ctx) {
1553 		hdd_err("HDD context is null");
1554 		return -EINVAL;
1555 	}
1556 
1557 	concurrent_state = policy_mgr_get_concurrency_mode(
1558 		hdd_ctx->psoc);
1559 	/*
1560 	 * Check if concurrency mode is active.
1561 	 * Need to modify this code to support MCC modes other than STA/P2P
1562 	 */
1563 	if (((concurrent_state & sta_cli_bit_mask) == sta_cli_bit_mask) ||
1564 	    ((concurrent_state & sta_go_bit_mask) == sta_go_bit_mask)) {
1565 		hdd_info("STA & P2P are both enabled");
1566 
1567 		/*
1568 		 * The channel numbers for both adapters and the time
1569 		 * quota for the 1st adapter, i.e., one specified in cmd
1570 		 * are formatted as a bit vector then passed on to WMA
1571 		 * +***********************************************************+
1572 		 * |bit 31-24  | bit 23-16  |   bits 15-8   |   bits 7-0       |
1573 		 * |  Unused   | Quota for  | chan. # for   |   chan. # for    |
1574 		 * |           | 1st chan.  | 1st chan.     |   2nd chan.      |
1575 		 * +***********************************************************+
1576 		 */
1577 
1578 		set_value = set_first_connection_operating_channel(
1579 			hdd_ctx, set_value, adapter->device_mode);
1580 
1581 		set_value = set_second_connection_operating_channel(
1582 			hdd_ctx, set_value, adapter->deflink->vdev_id);
1583 
1584 		ret = wlan_hdd_send_mcc_vdev_quota(adapter, set_value);
1585 	} else {
1586 		hdd_info("MCC is not active. Exit w/o setting latency");
1587 	}
1588 
1589 	return ret;
1590 }
1591 
wlan_hdd_go_set_mcc_p2p_quota(struct hdd_adapter * hostapd_adapter,uint32_t set_value)1592 int wlan_hdd_go_set_mcc_p2p_quota(struct hdd_adapter *hostapd_adapter,
1593 				  uint32_t set_value)
1594 {
1595 	return wlan_hdd_set_mcc_p2p_quota(hostapd_adapter, set_value);
1596 }
1597 
wlan_hdd_set_mcc_latency(struct hdd_adapter * adapter,int set_value)1598 void wlan_hdd_set_mcc_latency(struct hdd_adapter *adapter, int set_value)
1599 {
1600 	uint32_t concurrent_state;
1601 	struct hdd_context *hdd_ctx;
1602 	uint32_t sta_cli_bit_mask = QDF_STA_MASK | QDF_P2P_CLIENT_MASK;
1603 	uint32_t sta_go_bit_mask = QDF_STA_MASK | QDF_P2P_GO_MASK;
1604 
1605 	if (!adapter) {
1606 		hdd_err("Invalid adapter");
1607 		return;
1608 	}
1609 
1610 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1611 	if (!hdd_ctx) {
1612 		hdd_err("HDD context is null");
1613 		return;
1614 	}
1615 
1616 	concurrent_state = policy_mgr_get_concurrency_mode(
1617 		hdd_ctx->psoc);
1618 	/**
1619 	 * Check if concurrency mode is active.
1620 	 * Need to modify this code to support MCC modes other than STA/P2P
1621 	 */
1622 	if (((concurrent_state & sta_cli_bit_mask) == sta_cli_bit_mask) ||
1623 	    ((concurrent_state & sta_go_bit_mask) == sta_go_bit_mask)) {
1624 		hdd_info("STA & P2P are both enabled");
1625 		/*
1626 		 * The channel number and latency are formatted in
1627 		 * a bit vector then passed on to WMA layer.
1628 		 * +**********************************************+
1629 		 * |bits 31-16 |      bits 15-8    |  bits 7-0    |
1630 		 * |  Unused   | latency - Chan. 1 |  channel no. |
1631 		 * +**********************************************+
1632 		 */
1633 		set_value = set_first_connection_operating_channel(
1634 			hdd_ctx, set_value, adapter->device_mode);
1635 
1636 		wlan_hdd_send_mcc_latency(adapter, set_value);
1637 	} else {
1638 		hdd_info("MCC is not active. Exit w/o setting latency");
1639 	}
1640 }
1641