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