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