xref: /wlan-dirver/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c (revision 32f63dc370adac4d2694d98ae22869c1330dc253)
1 /*
2  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-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_cfg80211.c
22  *
23  * WLAN Host Device Driver cfg80211 APIs implementation
24  *
25  */
26 
27 #include <linux/version.h>
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/init.h>
31 #include <linux/etherdevice.h>
32 #include <linux/wireless.h>
33 #include "osif_sync.h"
34 #include <wlan_hdd_includes.h>
35 #include <net/arp.h>
36 #include <net/cfg80211.h>
37 #include <net/mac80211.h>
38 #include <wlan_hdd_wowl.h>
39 #include <ani_global.h>
40 #include "sir_params.h"
41 #include "dot11f.h"
42 #include "wlan_hdd_assoc.h"
43 #include "wlan_hdd_wext.h"
44 #include "sme_api.h"
45 #include "sme_power_save_api.h"
46 #include "wlan_hdd_p2p.h"
47 #include "wlan_hdd_cfg80211.h"
48 #include "wlan_hdd_hostapd.h"
49 #include "wlan_hdd_softap_tx_rx.h"
50 #include "wlan_hdd_main.h"
51 #include "wlan_hdd_power.h"
52 #include "wlan_hdd_trace.h"
53 #include "wlan_hdd_tx_rx.h"
54 #include "qdf_str.h"
55 #include "qdf_trace.h"
56 #include "qdf_types.h"
57 #include "qdf_net_if.h"
58 #include "cds_utils.h"
59 #include "cds_sched.h"
60 #include "wlan_hdd_scan.h"
61 #include <qc_sap_ioctl.h>
62 #include "wlan_hdd_tdls.h"
63 #include "wlan_hdd_wmm.h"
64 #include "wma_types.h"
65 #include "wma.h"
66 #include "wma_twt.h"
67 #include "wlan_hdd_misc.h"
68 #include "wlan_hdd_nan.h"
69 #include "wlan_logging_sock_svc.h"
70 #include "sap_api.h"
71 #include "csr_api.h"
72 #include "pld_common.h"
73 #include "wmi_unified_param.h"
74 
75 #include <cdp_txrx_handle.h>
76 #include <wlan_cfg80211_scan.h>
77 #include <wlan_cfg80211_ftm.h>
78 
79 #include "wlan_hdd_ext_scan.h"
80 
81 #include "wlan_hdd_stats.h"
82 #include "cds_api.h"
83 #include "wlan_policy_mgr_api.h"
84 #include "qwlan_version.h"
85 
86 #include "wlan_hdd_ocb.h"
87 #include "wlan_hdd_tsf.h"
88 
89 #include "sap_internal.h"
90 
91 #include "wlan_hdd_green_ap.h"
92 
93 #include "wlan_hdd_subnet_detect.h"
94 #include <wlan_hdd_regulatory.h>
95 #include "wlan_hdd_lpass.h"
96 #include "wlan_hdd_nan_datapath.h"
97 #include "wlan_hdd_disa.h"
98 #include "wlan_osif_request_manager.h"
99 #include "wlan_hdd_he.h"
100 #ifdef FEATURE_WLAN_APF
101 #include "wlan_hdd_apf.h"
102 #endif
103 #include "wlan_hdd_fw_state.h"
104 #include "wlan_hdd_mpta_helper.h"
105 
106 #include <cdp_txrx_cmn.h>
107 #include <cdp_txrx_misc.h>
108 #include <cdp_txrx_ctrl.h>
109 #include "wlan_pmo_ucfg_api.h"
110 #include "os_if_wifi_pos.h"
111 #include "wlan_utility.h"
112 #include "wlan_reg_ucfg_api.h"
113 #include "wifi_pos_api.h"
114 #include "wlan_hdd_spectralscan.h"
115 #include "wlan_ipa_ucfg_api.h"
116 #include <wlan_cfg80211_mc_cp_stats.h>
117 #include <wlan_cp_stats_mc_ucfg_api.h>
118 #include "wlan_tdls_cfg_api.h"
119 #include "wlan_tdls_ucfg_api.h"
120 #include <wlan_hdd_bss_transition.h>
121 #include <wlan_hdd_concurrency_matrix.h>
122 #include <wlan_hdd_p2p_listen_offload.h>
123 #include <wlan_hdd_rssi_monitor.h>
124 #include <wlan_hdd_sap_cond_chan_switch.h>
125 #include <wlan_hdd_station_info.h>
126 #include <wlan_hdd_tx_power.h>
127 #include <wlan_hdd_active_tos.h>
128 #include <wlan_hdd_sar_limits.h>
129 #include <wlan_hdd_ota_test.h>
130 #include "wlan_policy_mgr_ucfg.h"
131 #include "wlan_mlme_ucfg_api.h"
132 #include "wlan_mlme_twt_ucfg_api.h"
133 #include "wlan_mlme_public_struct.h"
134 #include "wlan_extscan_ucfg_api.h"
135 #include "wlan_pmo_cfg.h"
136 #include "cfg_ucfg_api.h"
137 
138 #include "wlan_crypto_def_i.h"
139 #include "wlan_crypto_global_api.h"
140 #include "wlan_nl_to_crypto_params.h"
141 #include "wlan_crypto_global_def.h"
142 #include "cdp_txrx_cfg.h"
143 #include "wlan_hdd_object_manager.h"
144 #include "nan_ucfg_api.h"
145 #include "wlan_fwol_ucfg_api.h"
146 #include "wlan_cfg80211_crypto.h"
147 #include "wlan_cfg80211_interop_issues_ap.h"
148 #include "wlan_scan_ucfg_api.h"
149 #include "wlan_hdd_coex_config.h"
150 #include "wlan_hdd_bcn_recv.h"
151 #include "wlan_hdd_connectivity_logging.h"
152 #include "wlan_dlm_ucfg_api.h"
153 #include "wlan_hdd_hw_capability.h"
154 #include "wlan_hdd_oemdata.h"
155 #include "os_if_fwol.h"
156 #include "wlan_hdd_sta_info.h"
157 #include "sme_api.h"
158 #include "wlan_hdd_thermal.h"
159 #include <ol_defines.h>
160 #include "wlan_hdd_btc_chain_mode.h"
161 #include "os_if_nan.h"
162 #include "wlan_hdd_apf.h"
163 #include "wlan_hdd_cfr.h"
164 #include "wlan_hdd_ioctl.h"
165 #include "wlan_cm_roam_ucfg_api.h"
166 #include "hif.h"
167 #include "wlan_reg_ucfg_api.h"
168 #include "wlan_hdd_afc.h"
169 #include "wlan_hdd_twt.h"
170 #include "wlan_hdd_gpio.h"
171 #include "wlan_hdd_medium_assess.h"
172 #include "wlan_if_mgr_ucfg_api.h"
173 #include "wlan_if_mgr_public_struct.h"
174 #include "wlan_wfa_ucfg_api.h"
175 #include "wifi_pos_ucfg_i.h"
176 #include <osif_cm_util.h>
177 #include <osif_cm_req.h>
178 #include "wlan_hdd_bootup_marker.h"
179 #include "wlan_hdd_cm_api.h"
180 #include "wlan_roam_debug.h"
181 #include "wlan_hdd_avoid_freq_ext.h"
182 #include "qdf_util.h"
183 #include "wlan_hdd_mdns_offload.h"
184 #include "wlan_pkt_capture_ucfg_api.h"
185 #include "wifi_pos_public_struct.h"
186 #include "wifi_pos_pasn_api.h"
187 #include "os_if_pkt_capture.h"
188 #include "os_if_dp_local_pkt_capture.h"
189 #include "wlan_hdd_son.h"
190 #include "wlan_hdd_mcc_quota.h"
191 #include "wlan_hdd_peer_txq_flush.h"
192 #include "wlan_cfg80211_wifi_pos.h"
193 #include "wlan_osif_features.h"
194 #include "wlan_hdd_wifi_pos_pasn.h"
195 #include "wlan_coex_ucfg_api.h"
196 #include "wlan_coex_public_structs.h"
197 #include "wlan_dp_ucfg_api.h"
198 #include "os_if_dp.h"
199 #include "os_if_dp_lro.h"
200 #include "wlan_mlo_mgr_sta.h"
201 #include <wlan_mlo_mgr_peer.h>
202 #include "wlan_hdd_coap.h"
203 #include "wlan_hdd_tdls.h"
204 #include "wlan_psoc_mlme_api.h"
205 #include <utils_mlo.h>
206 #include "wlan_mlo_mgr_roam.h"
207 #include "wlan_hdd_mlo.h"
208 #include <wlan_psoc_mlme_ucfg_api.h>
209 #include "wlan_epcs_api.h"
210 #include "wlan_mlo_epcs_ucfg_api.h"
211 #include <wlan_ll_sap_ucfg_api.h>
212 #include <wlan_mlo_mgr_link_switch.h>
213 #include <wlan_hdd_ll_lt_sap.h>
214 #include "wlan_cp_stats_mc_defs.h"
215 #include "wlan_policy_mgr_ll_sap.h"
216 
217 /*
218  * A value of 100 (milliseconds) can be sent to FW.
219  * FW would enable Tx beamforming based on this.
220  */
221 #define TX_BFER_NDP_PERIODICITY 100
222 
223 #define g_mode_rates_size (12)
224 #define a_mode_rates_size (8)
225 
226 #define WLAN_WAIT_WLM_LATENCY_LEVEL 1000
227 
228 /*
229  * BIT map values for vdev_param_set_profile
230  * bit 0: 0 - XR SAP profile disabled
231  *        1 - XR SAP profile enabled
232  * bit 1: 0 - XPAN profile disabled
233  *        1 - XPAN profile enabled
234  */
235 #define AP_PROFILE_XR_ENABLE 0x1
236 #define AP_PROFILE_XPAN_ENABLE 0x2
237 
238 /**
239  * rtt_is_enabled - Macro to check if the bitmap has any RTT roles set
240  * @bitmap: The bitmap to be checked
241  */
242 #define rtt_is_enabled(bitmap) \
243 	((bitmap) & (WMI_FW_STA_RTT_INITR | \
244 		     WMI_FW_STA_RTT_RESPR | \
245 		     WMI_FW_AP_RTT_INITR | \
246 		     WMI_FW_AP_RTT_RESPR))
247 
248 /*
249  * Android CTS verifier needs atleast this much wait time (in msec)
250  */
251 #define MAX_REMAIN_ON_CHANNEL_DURATION (2000)
252 
253 #define HDD2GHZCHAN(freq, chan, flag)   {     \
254 		.band = HDD_NL80211_BAND_2GHZ, \
255 		.center_freq = (freq), \
256 		.hw_value = (chan), \
257 		.flags = (flag), \
258 		.max_antenna_gain = 0, \
259 		.max_power = 0, \
260 }
261 
262 #define HDD5GHZCHAN(freq, chan, flag)   {     \
263 		.band =  HDD_NL80211_BAND_5GHZ, \
264 		.center_freq = (freq), \
265 		.hw_value = (chan), \
266 		.flags = (flag), \
267 		.max_antenna_gain = 0, \
268 		.max_power = 0, \
269 }
270 
271 #define HDD_G_MODE_RATETAB(rate, rate_id, flag)	\
272 	{ \
273 		.bitrate = rate, \
274 		.hw_value = rate_id, \
275 		.flags = flag, \
276 	}
277 
278 #define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
279 			mode <= DFS_MODE_DEPRIORITIZE))
280 
281 #ifndef WLAN_CIPHER_SUITE_GCMP
282 #define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
283 #endif
284 #ifndef WLAN_CIPHER_SUITE_GCMP_256
285 #define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
286 #endif
287 
288 /* Default number of Simultaneous Transmit */
289 #define DEFAULT_MAX_STR_LINK_COUNT 1
290 /* Maximum number of Simultaneous Transmit */
291 #define MAX_STR_LINK_COUNT 2
292 
293 static const u32 hdd_gcmp_cipher_suits[] = {
294 	WLAN_CIPHER_SUITE_GCMP,
295 	WLAN_CIPHER_SUITE_GCMP_256,
296 };
297 
298 static const u32 hdd_cipher_suites[] = {
299 	WLAN_CIPHER_SUITE_WEP40,
300 	WLAN_CIPHER_SUITE_WEP104,
301 	WLAN_CIPHER_SUITE_TKIP,
302 #ifdef FEATURE_WLAN_ESE
303 #define WLAN_CIPHER_SUITE_BTK 0x004096fe        /* use for BTK */
304 #define WLAN_CIPHER_SUITE_KRK 0x004096ff        /* use for KRK */
305 	WLAN_CIPHER_SUITE_BTK,
306 	WLAN_CIPHER_SUITE_KRK,
307 	WLAN_CIPHER_SUITE_CCMP,
308 #else
309 	WLAN_CIPHER_SUITE_CCMP,
310 #endif
311 #ifdef FEATURE_WLAN_WAPI
312 	WLAN_CIPHER_SUITE_SMS4,
313 #endif
314 	WLAN_CIPHER_SUITE_AES_CMAC,
315 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
316 	WLAN_CIPHER_SUITE_BIP_GMAC_128,
317 	WLAN_CIPHER_SUITE_BIP_GMAC_256,
318 #endif
319 };
320 
321 static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
322 	HDD2GHZCHAN(2412, 1, 0),
323 	HDD2GHZCHAN(2417, 2, 0),
324 	HDD2GHZCHAN(2422, 3, 0),
325 	HDD2GHZCHAN(2427, 4, 0),
326 	HDD2GHZCHAN(2432, 5, 0),
327 	HDD2GHZCHAN(2437, 6, 0),
328 	HDD2GHZCHAN(2442, 7, 0),
329 	HDD2GHZCHAN(2447, 8, 0),
330 	HDD2GHZCHAN(2452, 9, 0),
331 	HDD2GHZCHAN(2457, 10, 0),
332 	HDD2GHZCHAN(2462, 11, 0),
333 	HDD2GHZCHAN(2467, 12, 0),
334 	HDD2GHZCHAN(2472, 13, 0),
335 	HDD2GHZCHAN(2484, 14, 0),
336 };
337 
338 static const struct ieee80211_channel hdd_channels_5_ghz[] = {
339 	HDD5GHZCHAN(5180, 36, 0),
340 	HDD5GHZCHAN(5200, 40, 0),
341 	HDD5GHZCHAN(5220, 44, 0),
342 	HDD5GHZCHAN(5240, 48, 0),
343 	HDD5GHZCHAN(5260, 52, 0),
344 	HDD5GHZCHAN(5280, 56, 0),
345 	HDD5GHZCHAN(5300, 60, 0),
346 	HDD5GHZCHAN(5320, 64, 0),
347 	HDD5GHZCHAN(5500, 100, 0),
348 	HDD5GHZCHAN(5520, 104, 0),
349 	HDD5GHZCHAN(5540, 108, 0),
350 	HDD5GHZCHAN(5560, 112, 0),
351 	HDD5GHZCHAN(5580, 116, 0),
352 	HDD5GHZCHAN(5600, 120, 0),
353 	HDD5GHZCHAN(5620, 124, 0),
354 	HDD5GHZCHAN(5640, 128, 0),
355 	HDD5GHZCHAN(5660, 132, 0),
356 	HDD5GHZCHAN(5680, 136, 0),
357 	HDD5GHZCHAN(5700, 140, 0),
358 	HDD5GHZCHAN(5720, 144, 0),
359 	HDD5GHZCHAN(5745, 149, 0),
360 	HDD5GHZCHAN(5765, 153, 0),
361 	HDD5GHZCHAN(5785, 157, 0),
362 	HDD5GHZCHAN(5805, 161, 0),
363 	HDD5GHZCHAN(5825, 165, 0),
364 };
365 
366 #ifdef WLAN_FEATURE_DSRC
367 static const struct ieee80211_channel hdd_channels_dot11p[] = {
368 	HDD5GHZCHAN(5852, 170, 0),
369 	HDD5GHZCHAN(5855, 171, 0),
370 	HDD5GHZCHAN(5860, 172, 0),
371 	HDD5GHZCHAN(5865, 173, 0),
372 	HDD5GHZCHAN(5870, 174, 0),
373 	HDD5GHZCHAN(5875, 175, 0),
374 	HDD5GHZCHAN(5880, 176, 0),
375 	HDD5GHZCHAN(5885, 177, 0),
376 	HDD5GHZCHAN(5890, 178, 0),
377 	HDD5GHZCHAN(5895, 179, 0),
378 	HDD5GHZCHAN(5900, 180, 0),
379 	HDD5GHZCHAN(5905, 181, 0),
380 	HDD5GHZCHAN(5910, 182, 0),
381 	HDD5GHZCHAN(5915, 183, 0),
382 	HDD5GHZCHAN(5920, 184, 0),
383 };
384 #else
385 static const struct ieee80211_channel hdd_5dot9_ghz_ch[] = {
386 	HDD5GHZCHAN(5845, 169, 0),
387 	HDD5GHZCHAN(5865, 173, 0),
388 	HDD5GHZCHAN(5885, 177, 0),
389 };
390 #endif
391 
392 #define band_2_ghz_channels_size sizeof(hdd_channels_2_4_ghz)
393 
394 #ifdef WLAN_FEATURE_DSRC
395 #define band_5_ghz_channels_size (sizeof(hdd_channels_5_ghz) + \
396 	sizeof(hdd_channels_dot11p))
397 #else
398 #define band_5_ghz_channels_size (sizeof(hdd_channels_5_ghz) + \
399 	sizeof(hdd_5dot9_ghz_ch))
400 #endif
401 
402 static struct ieee80211_rate g_mode_rates[] = {
403 	HDD_G_MODE_RATETAB(10, 0x1, 0),
404 	HDD_G_MODE_RATETAB(20, 0x2, 0),
405 	HDD_G_MODE_RATETAB(55, 0x4, 0),
406 	HDD_G_MODE_RATETAB(110, 0x8, 0),
407 	HDD_G_MODE_RATETAB(60, 0x10, 0),
408 	HDD_G_MODE_RATETAB(90, 0x20, 0),
409 	HDD_G_MODE_RATETAB(120, 0x40, 0),
410 	HDD_G_MODE_RATETAB(180, 0x80, 0),
411 	HDD_G_MODE_RATETAB(240, 0x100, 0),
412 	HDD_G_MODE_RATETAB(360, 0x200, 0),
413 	HDD_G_MODE_RATETAB(480, 0x400, 0),
414 	HDD_G_MODE_RATETAB(540, 0x800, 0),
415 };
416 
417 static struct ieee80211_rate a_mode_rates[] = {
418 	HDD_G_MODE_RATETAB(60, 0x10, 0),
419 	HDD_G_MODE_RATETAB(90, 0x20, 0),
420 	HDD_G_MODE_RATETAB(120, 0x40, 0),
421 	HDD_G_MODE_RATETAB(180, 0x80, 0),
422 	HDD_G_MODE_RATETAB(240, 0x100, 0),
423 	HDD_G_MODE_RATETAB(360, 0x200, 0),
424 	HDD_G_MODE_RATETAB(480, 0x400, 0),
425 	HDD_G_MODE_RATETAB(540, 0x800, 0),
426 };
427 
428 static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
429 	.channels = NULL,
430 	.n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
431 	.band = HDD_NL80211_BAND_2GHZ,
432 	.bitrates = g_mode_rates,
433 	.n_bitrates = g_mode_rates_size,
434 	.ht_cap.ht_supported = 1,
435 	.ht_cap.cap = IEEE80211_HT_CAP_SGI_20
436 		      | IEEE80211_HT_CAP_GRN_FLD
437 		      | IEEE80211_HT_CAP_DSSSCCK40
438 		      | IEEE80211_HT_CAP_LSIG_TXOP_PROT
439 		      | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
440 	.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
441 	.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
442 	.ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
443 	.ht_cap.mcs.rx_highest = cpu_to_le16(72),
444 	.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
445 };
446 
447 static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
448 	.channels = NULL,
449 	.n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
450 	.band = HDD_NL80211_BAND_5GHZ,
451 	.bitrates = a_mode_rates,
452 	.n_bitrates = a_mode_rates_size,
453 	.ht_cap.ht_supported = 1,
454 	.ht_cap.cap = IEEE80211_HT_CAP_SGI_20
455 		      | IEEE80211_HT_CAP_GRN_FLD
456 		      | IEEE80211_HT_CAP_DSSSCCK40
457 		      | IEEE80211_HT_CAP_LSIG_TXOP_PROT
458 		      | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
459 	.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
460 	.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
461 	.ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
462 	.ht_cap.mcs.rx_highest = cpu_to_le16(72),
463 	.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
464 	.vht_cap.vht_supported = 1,
465 };
466 
467 enum hdd_hw_rate_cck {
468 	HDD_HW_RATE_CCK_LP_11M = 0,
469 	HDD_HW_RATE_CCK_LP_5_5M,
470 	HDD_HW_RATE_CCK_LP_2M,
471 	HDD_HW_RATE_CCK_LP_1M,
472 	HDD_HW_RATE_CCK_SP_11M,
473 	HDD_HW_RATE_CCK_SP_5_5M,
474 	HDD_HW_RATE_CCK_SP_2M,
475 };
476 
477 enum hdd_hw_rate_ofdm {
478 	HDD_HW_RATE_OFDM_48M = 0,
479 	HDD_HW_RATE_OFDM_24M,
480 	HDD_HW_RATE_OFDM_12M,
481 	HDD_HW_RATE_OFDM_6M,
482 	HDD_HW_RATE_OFDM_54M,
483 	HDD_HW_RATE_OFDM_36M,
484 	HDD_HW_RATE_OFDM_18M,
485 	HDD_HW_RATE_OFDM_9M,
486 };
487 
488 static struct ieee80211_rate hdd_legacy_rates[] = {
489 	{ .bitrate = 10,
490 	  .hw_value = HDD_HW_RATE_CCK_LP_1M },
491 	{ .bitrate = 20,
492 	  .hw_value = HDD_HW_RATE_CCK_LP_2M },
493 	{ .bitrate = 55,
494 	  .hw_value = HDD_HW_RATE_CCK_LP_5_5M },
495 	{ .bitrate = 110,
496 	  .hw_value = HDD_HW_RATE_CCK_LP_11M },
497 	{ .bitrate = 60, .hw_value = HDD_HW_RATE_OFDM_6M },
498 	{ .bitrate = 90, .hw_value = HDD_HW_RATE_OFDM_9M },
499 	{ .bitrate = 120, .hw_value = HDD_HW_RATE_OFDM_12M },
500 	{ .bitrate = 180, .hw_value = HDD_HW_RATE_OFDM_18M },
501 	{ .bitrate = 240, .hw_value = HDD_HW_RATE_OFDM_24M },
502 	{ .bitrate = 360, .hw_value = HDD_HW_RATE_OFDM_36M },
503 	{ .bitrate = 480, .hw_value = HDD_HW_RATE_OFDM_48M },
504 	{ .bitrate = 540, .hw_value = HDD_HW_RATE_OFDM_54M },
505 };
506 
507 #if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
508 	(KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
509 
510 static struct ieee80211_channel hdd_channels_6_ghz[NUM_6GHZ_CHANNELS];
511 
512 static struct ieee80211_supported_band wlan_hdd_band_6_ghz = {
513 	.channels = NULL,
514 	.n_channels = 0,
515 	.band = HDD_NL80211_BAND_6GHZ,
516 	.bitrates = a_mode_rates,
517 	.n_bitrates = a_mode_rates_size,
518 };
519 
520 #define HDD_SET_6GHZCHAN(ch, freq, chan, flag)   {     \
521 		(ch).band =  HDD_NL80211_BAND_6GHZ; \
522 		(ch).center_freq = (freq); \
523 		(ch).hw_value = (chan); \
524 		(ch).flags = (flag); \
525 		(ch).max_antenna_gain = 0; \
526 		(ch).max_power = 0; \
527 }
528 
529 static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
530 {
531 	uint32_t i;
532 	struct wiphy *wiphy = hdd_ctx->wiphy;
533 	struct ieee80211_channel *chlist = hdd_channels_6_ghz;
534 	uint32_t num = ARRAY_SIZE(hdd_channels_6_ghz);
535 	uint16_t base_freq;
536 	QDF_STATUS status;
537 	uint32_t band_capability;
538 
539 	hdd_enter();
540 
541 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
542 	if (QDF_IS_STATUS_ERROR(status)) {
543 		hdd_err("Failed to get MLME Band Capability");
544 		return;
545 	}
546 
547 	if (!(band_capability & (BIT(REG_BAND_6G)))) {
548 		hdd_debug("6ghz band not enabled");
549 		return;
550 	}
551 
552 	qdf_mem_zero(chlist, sizeof(*chlist) * num);
553 	base_freq = wlan_reg_min_6ghz_chan_freq();
554 
555 	for (i = 0; i < num; i++)
556 		HDD_SET_6GHZCHAN(chlist[i],
557 				 base_freq + i * 20,
558 				 wlan_reg_freq_to_chan(hdd_ctx->pdev,
559 						       base_freq + i * 20),
560 				 IEEE80211_CHAN_DISABLED);
561 	wiphy->bands[HDD_NL80211_BAND_6GHZ] = &wlan_hdd_band_6_ghz;
562 	wiphy->bands[HDD_NL80211_BAND_6GHZ]->channels = chlist;
563 	wiphy->bands[HDD_NL80211_BAND_6GHZ]->n_channels = num;
564 
565 	hdd_exit();
566 }
567 
568 /**
569  * wlan_hdd_populate_6g_chan_info() - Populate 6 GHz chan info in hdd context
570  * @hdd_ctx: pointer to hdd context
571  * @index: 6 GHz channel beginning index in chan_info of @hdd_ctx
572  *
573  * Return: Number of 6 GHz channels populated
574  */
575 static uint32_t
576 wlan_hdd_populate_6g_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
577 {
578 	uint32_t num_6g, i;
579 	struct scan_chan_info *chan_info;
580 
581 	if (!hdd_ctx->wiphy->bands[HDD_NL80211_BAND_6GHZ] ||
582 	    !hdd_ctx->wiphy->bands[HDD_NL80211_BAND_6GHZ]->n_channels) {
583 		hdd_debug("6GHz channel list not populated to wiphy");
584 		return 0;
585 	}
586 
587 	num_6g = QDF_ARRAY_SIZE(hdd_channels_6_ghz);
588 	chan_info = hdd_ctx->chan_info;
589 
590 	for (i = 0; i < num_6g; i++)
591 		chan_info[index + i].freq = hdd_channels_6_ghz[i].center_freq;
592 
593 	return num_6g;
594 }
595 
596 #else
597 static void hdd_init_6ghz(struct hdd_context *hdd_ctx)
598 {
599 }
600 
601 static inline uint32_t
602 wlan_hdd_populate_6g_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
603 {
604 	return 0;
605 }
606 #endif
607 
608 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) || \
609 	defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
610 /*akm suits supported by sta*/
611 static const u32 hdd_sta_akm_suites[] = {
612 	WLAN_AKM_SUITE_8021X,
613 	WLAN_AKM_SUITE_PSK,
614 	WLAN_AKM_SUITE_FT_8021X,
615 	WLAN_AKM_SUITE_FT_PSK,
616 	WLAN_AKM_SUITE_8021X_SHA256,
617 	WLAN_AKM_SUITE_PSK_SHA256,
618 	WLAN_AKM_SUITE_TDLS,
619 	WLAN_AKM_SUITE_SAE,
620 	WLAN_AKM_SUITE_FT_OVER_SAE,
621 	WLAN_AKM_SUITE_EAP_SHA256,
622 	WLAN_AKM_SUITE_EAP_SHA384,
623 	WLAN_AKM_SUITE_FILS_SHA256,
624 	WLAN_AKM_SUITE_FILS_SHA384,
625 	WLAN_AKM_SUITE_FT_FILS_SHA256,
626 	WLAN_AKM_SUITE_FT_FILS_SHA384,
627 	WLAN_AKM_SUITE_OWE,
628 	WLAN_AKM_SUITE_DPP_RSN,
629 	WLAN_AKM_SUITE_FT_EAP_SHA_384,
630 	RSN_AUTH_KEY_MGMT_CCKM,
631 	RSN_AUTH_KEY_MGMT_OSEN,
632 	WAPI_PSK_AKM_SUITE,
633 	WAPI_CERT_AKM_SUITE,
634 	WLAN_AKM_SUITE_SAE_EXT_KEY,
635 	WLAN_AKM_SUITE_FT_SAE_EXT_KEY,
636 };
637 
638 /*akm suits supported by AP*/
639 static const u32 hdd_ap_akm_suites[] = {
640 	WLAN_AKM_SUITE_PSK,
641 	WLAN_AKM_SUITE_SAE,
642 	WLAN_AKM_SUITE_OWE,
643 };
644 
645 /* This structure contain information what akm suits are
646  * supported for each mode
647  */
648 static const struct wiphy_iftype_akm_suites
649 	wlan_hdd_akm_suites[] = {
650 	{
651 		.iftypes_mask = BIT(NL80211_IFTYPE_STATION) |
652 				BIT(NL80211_IFTYPE_P2P_CLIENT),
653 		.akm_suites = hdd_sta_akm_suites,
654 		.n_akm_suites = (sizeof(hdd_sta_akm_suites) / sizeof(u32)),
655 	},
656 	{
657 		.iftypes_mask = BIT(NL80211_IFTYPE_AP) |
658 				BIT(NL80211_IFTYPE_P2P_GO),
659 		.akm_suites = hdd_ap_akm_suites,
660 		.n_akm_suites = (sizeof(hdd_ap_akm_suites) / sizeof(u32)),
661 	},
662 };
663 #endif
664 
665 /* This structure contain information what kind of frame are expected in
666  * TX/RX direction for each kind of interface
667  */
668 static const struct ieee80211_txrx_stypes
669 	wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
670 	[NL80211_IFTYPE_STATION] = {
671 		.tx = 0xffff,
672 		.rx = BIT(SIR_MAC_MGMT_ACTION) |
673 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
674 		      BIT(SIR_MAC_MGMT_AUTH),
675 	},
676 	[NL80211_IFTYPE_AP] = {
677 		.tx = 0xffff,
678 		.rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
679 		      BIT(SIR_MAC_MGMT_REASSOC_REQ) |
680 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
681 		      BIT(SIR_MAC_MGMT_DISASSOC) |
682 		      BIT(SIR_MAC_MGMT_AUTH) |
683 		      BIT(SIR_MAC_MGMT_DEAUTH) |
684 		      BIT(SIR_MAC_MGMT_ACTION),
685 	},
686 	[NL80211_IFTYPE_ADHOC] = {
687 		.tx = 0xffff,
688 		.rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
689 		      BIT(SIR_MAC_MGMT_REASSOC_REQ) |
690 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
691 		      BIT(SIR_MAC_MGMT_DISASSOC) |
692 		      BIT(SIR_MAC_MGMT_AUTH) |
693 		      BIT(SIR_MAC_MGMT_DEAUTH) |
694 		      BIT(SIR_MAC_MGMT_ACTION),
695 	},
696 	[NL80211_IFTYPE_P2P_CLIENT] = {
697 		.tx = 0xffff,
698 		.rx = BIT(SIR_MAC_MGMT_ACTION) |
699 		      BIT(SIR_MAC_MGMT_AUTH) |
700 		      BIT(SIR_MAC_MGMT_PROBE_REQ),
701 	},
702 	[NL80211_IFTYPE_P2P_GO] = {
703 		/* This is also same as for SoftAP */
704 		.tx = 0xffff,
705 		.rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
706 		      BIT(SIR_MAC_MGMT_REASSOC_REQ) |
707 		      BIT(SIR_MAC_MGMT_PROBE_REQ) |
708 		      BIT(SIR_MAC_MGMT_DISASSOC) |
709 		      BIT(SIR_MAC_MGMT_AUTH) |
710 		      BIT(SIR_MAC_MGMT_DEAUTH) |
711 		      BIT(SIR_MAC_MGMT_ACTION),
712 	},
713 	[NL80211_IFTYPE_NAN] = {
714 		.tx = 0xffff,
715 		.rx = BIT(SIR_MAC_MGMT_AUTH),
716 	},
717 };
718 
719 /* Interface limits and combinations registered by the driver */
720 
721 /* STA ( + STA ) combination */
722 static const struct ieee80211_iface_limit
723 	wlan_hdd_sta_iface_limit[] = {
724 	{
725 		.max = 2,
726 		.types = BIT(NL80211_IFTYPE_STATION),
727 	},
728 };
729 
730 /* AP ( + AP ) combination */
731 static const struct ieee80211_iface_limit
732 	wlan_hdd_ap_iface_limit[] = {
733 	{
734 		.max = (QDF_MAX_NO_OF_SAP_MODE),
735 		.types = BIT(NL80211_IFTYPE_AP),
736 	},
737 };
738 
739 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
740 /* P2P limit */
741 static const struct ieee80211_iface_limit
742 	wlan_hdd_p2p_iface_limit[] = {
743 	{
744 		.max = 1,
745 		.types = BIT(NL80211_IFTYPE_P2P_CLIENT),
746 	},
747 	{
748 		.max = 1,
749 		.types = BIT(NL80211_IFTYPE_P2P_GO),
750 	},
751 };
752 
753 /* STA + P2P + P2P combination */
754 static const struct ieee80211_iface_limit
755 	wlan_hdd_sta_p2p_p2p_iface_limit[] = {
756 	{
757 		.max = 1,
758 		.types = BIT(NL80211_IFTYPE_STATION)
759 	},
760 	{
761 		/* Support for two identical (GO + GO or CLI + CLI)
762 		 * or dissimilar (GO + CLI) P2P interfaces
763 		 */
764 		.max = 2,
765 		.types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
766 	},
767 };
768 
769 /* STA + AP + P2P combination */
770 static const struct ieee80211_iface_limit
771 wlan_hdd_sta_ap_p2p_iface_limit[] = {
772 	{
773 	   .max = 1,
774 	   .types = BIT(NL80211_IFTYPE_STATION)
775 	},
776 	{
777 	   .max = 1,
778 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
779 	},
780 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
781 	{
782 	   .max = 1,
783 	   .types = BIT(NL80211_IFTYPE_AP)
784 	},
785 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
786 };
787 
788 /* SAP + P2P combination */
789 static const struct ieee80211_iface_limit
790 wlan_hdd_sap_p2p_iface_limit[] = {
791 	{
792 	   /* The p2p interface in SAP+P2P can be GO/CLI.
793 	    * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
794 	    */
795 	   .max = 1,
796 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
797 	},
798 	{
799 	   /* SAP+GO to support only one SAP interface */
800 	   .max = 1,
801 	   .types = BIT(NL80211_IFTYPE_AP)
802 	}
803 };
804 
805 /* P2P + P2P combination */
806 static const struct ieee80211_iface_limit
807 wlan_hdd_p2p_p2p_iface_limit[] = {
808 	{
809 	   /* The p2p interface in P2P+P2P can be GO/CLI.
810 	    * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
811 	    */
812 	   .max = 2,
813 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
814 	},
815 };
816 #elif defined(WLAN_FEATURE_STA_SAP_P2P_CONCURRENCY)
817 /* STA + AP + P2P combination */
818 static const struct ieee80211_iface_limit
819 wlan_hdd_sta_ap_p2p_iface_limit[] = {
820 	{
821 	   .max = 1,
822 	   .types = BIT(NL80211_IFTYPE_STATION)
823 	},
824 	{
825 	   .max = 1,
826 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
827 	},
828 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
829 	{
830 	   .max = 1,
831 	   .types = BIT(NL80211_IFTYPE_AP)
832 	},
833 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
834 };
835 #endif
836 
837 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
838 /* STA + AP combination */
839 static const struct ieee80211_iface_limit
840 wlan_hdd_sta_ap_iface_limit[] = {
841 	{
842 	   .max = 1,
843 	   .types = BIT(NL80211_IFTYPE_STATION)
844 	},
845 	{
846 	   .max = 1,
847 	   .types = BIT(NL80211_IFTYPE_AP)
848 	},
849 };
850 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
851 
852 /* STA + P2P combination */
853 static const struct ieee80211_iface_limit
854 	wlan_hdd_sta_p2p_iface_limit[] = {
855 	{
856 		.max = 1,
857 		.types = BIT(NL80211_IFTYPE_STATION)
858 	},
859 	{
860 		/* Support for either (GO or CLI) */
861 		.max = 1,
862 		.types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
863 	},
864 };
865 
866 /* Monitor interface */
867 static const struct ieee80211_iface_limit
868 	wlan_hdd_mon_iface_limit[] = {
869 	{
870 		.max = 2,
871 		.types = BIT(NL80211_IFTYPE_MONITOR),
872 	},
873 };
874 
875 #if defined(WLAN_FEATURE_NAN) && \
876 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
877 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
878 /* STA + NAN disc combination */
879 static const struct ieee80211_iface_limit
880 	wlan_hdd_sta_nan_iface_limit[] = {
881 	{
882 		/* STA */
883 		.max = 1,
884 		.types = BIT(NL80211_IFTYPE_STATION)
885 	},
886 	{
887 		/* NAN */
888 		.max = 1,
889 		.types = BIT(NL80211_IFTYPE_NAN),
890 	},
891 };
892 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
893 
894 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
895 /* SAP + NAN disc combination */
896 static const struct ieee80211_iface_limit
897 	wlan_hdd_sap_nan_iface_limit[] = {
898 	{
899 		/* SAP */
900 		.max = 1,
901 		.types = BIT(NL80211_IFTYPE_AP)
902 	},
903 	{
904 		/* NAN */
905 		.max = 1,
906 		.types = BIT(NL80211_IFTYPE_NAN),
907 	},
908 };
909 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
910 #endif /* WLAN_FEATURE_NAN */
911 
912 static struct ieee80211_iface_combination
913 	wlan_hdd_iface_combination[] = {
914 	/* STA */
915 	{
916 		.limits = wlan_hdd_sta_iface_limit,
917 		.num_different_channels = 2,
918 		.max_interfaces = 2,
919 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
920 	},
921 	/* AP */
922 	{
923 		.limits = wlan_hdd_ap_iface_limit,
924 		.num_different_channels = 2,
925 		.max_interfaces = (QDF_MAX_NO_OF_SAP_MODE),
926 		.n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
927 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
928 	defined(CFG80211_BEACON_INTERVAL_BACKPORT)
929 		.beacon_int_min_gcd = 1,
930 #endif
931 	},
932 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
933 	/* P2P */
934 	{
935 		.limits = wlan_hdd_p2p_iface_limit,
936 		.num_different_channels = 2,
937 		.max_interfaces = 2,
938 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
939 	},
940 	/* STA + P2P + P2P */
941 	{
942 		.limits = wlan_hdd_sta_p2p_p2p_iface_limit,
943 		.num_different_channels = 2,
944 		.max_interfaces = 3,
945 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_p2p_iface_limit),
946 		.beacon_int_infra_match = true,
947 	},
948 	/* STA + P2P + SAP */
949 	{
950 		.limits = wlan_hdd_sta_ap_p2p_iface_limit,
951 		/* we can allow 3 channels for three different persona
952 		 * but due to firmware limitation, allow max 2 concrnt channels.
953 		 */
954 		.num_different_channels = 2,
955 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
956 		.max_interfaces = 3,
957 #else
958 		.max_interfaces = 2,
959 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
960 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2p_iface_limit),
961 		.beacon_int_infra_match = true,
962 	},
963 	/* SAP + P2P */
964 	{
965 		.limits = wlan_hdd_sap_p2p_iface_limit,
966 		.num_different_channels = 2,
967 		/* 1-SAP + 1-P2P */
968 		.max_interfaces = 2,
969 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
970 		.beacon_int_infra_match = true,
971 	},
972 	/* P2P + P2P */
973 	{
974 		.limits = wlan_hdd_p2p_p2p_iface_limit,
975 		.num_different_channels = 2,
976 		/* 2-P2P */
977 		.max_interfaces = 2,
978 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
979 		.beacon_int_infra_match = true,
980 	},
981 #elif defined(WLAN_FEATURE_STA_SAP_P2P_CONCURRENCY)
982 	/* STA + P2P + SAP */
983 	{
984 		.limits = wlan_hdd_sta_ap_p2p_iface_limit,
985 		/* we can allow 3 channels for three different persona
986 		 * but due to firmware limitation, allow max 2 concrnt channels.
987 		 */
988 		.num_different_channels = 2,
989 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
990 		.max_interfaces = 3,
991 #else
992 		.max_interfaces = 2,
993 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
994 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2p_iface_limit),
995 		.beacon_int_infra_match = true,
996 	},
997 #endif /* WLAN_FEATURE_NO_P2P_CONCURRENCY */
998 	/* STA + P2P */
999 	{
1000 		.limits = wlan_hdd_sta_p2p_iface_limit,
1001 		.num_different_channels = 2,
1002 		.max_interfaces = 2,
1003 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
1004 		.beacon_int_infra_match = true,
1005 	},
1006 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
1007 	/* STA + SAP */
1008 	{
1009 		.limits = wlan_hdd_sta_ap_iface_limit,
1010 		.num_different_channels = 2,
1011 		.max_interfaces = 2,
1012 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
1013 		.beacon_int_infra_match = true,
1014 	},
1015 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
1016 	/* Monitor */
1017 	{
1018 		.limits = wlan_hdd_mon_iface_limit,
1019 		.max_interfaces = 2,
1020 		.num_different_channels = 2,
1021 		.n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
1022 	},
1023 #if defined(WLAN_FEATURE_NAN) && \
1024 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
1025 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
1026 	/* NAN + STA */
1027 	{
1028 		.limits = wlan_hdd_sta_nan_iface_limit,
1029 		.max_interfaces = 2,
1030 		.num_different_channels = 2,
1031 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_nan_iface_limit),
1032 	},
1033 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
1034 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
1035 	/* NAN + SAP */
1036 	{
1037 		.limits = wlan_hdd_sap_nan_iface_limit,
1038 		.num_different_channels = 2,
1039 		.max_interfaces = 2,
1040 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_nan_iface_limit),
1041 		.beacon_int_infra_match = true,
1042 	},
1043 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
1044 #endif /* WLAN_FEATURE_NAN */
1045 };
1046 
1047 /* 1 and 2 port concurrencies */
1048 static struct ieee80211_iface_combination
1049 	wlan_hdd_derived_combination[] = {
1050 	/* STA */
1051 	{
1052 		.limits = wlan_hdd_sta_iface_limit,
1053 		.num_different_channels = 2,
1054 		.max_interfaces = 2,
1055 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
1056 	},
1057 	/* AP */
1058 	{
1059 		.limits = wlan_hdd_ap_iface_limit,
1060 		.num_different_channels = 2,
1061 		.max_interfaces = (QDF_MAX_NO_OF_SAP_MODE),
1062 		.n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
1063 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
1064 	defined(CFG80211_BEACON_INTERVAL_BACKPORT)
1065 		.beacon_int_min_gcd = 1,
1066 #endif
1067 	},
1068 #ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
1069 	/* P2P */
1070 	{
1071 		.limits = wlan_hdd_p2p_iface_limit,
1072 		.num_different_channels = 2,
1073 		.max_interfaces = 2,
1074 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
1075 	},
1076 
1077 	/* SAP + P2P */
1078 	{
1079 		.limits = wlan_hdd_sap_p2p_iface_limit,
1080 		.num_different_channels = 2,
1081 		/* 1-SAP + 1-P2P */
1082 		.max_interfaces = 2,
1083 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
1084 		.beacon_int_infra_match = true,
1085 	},
1086 	/* P2P + P2P */
1087 	{
1088 		.limits = wlan_hdd_p2p_p2p_iface_limit,
1089 		.num_different_channels = 2,
1090 		/* 2-P2P */
1091 		.max_interfaces = 2,
1092 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
1093 		.beacon_int_infra_match = true,
1094 	},
1095 #endif
1096 	/* STA + P2P */
1097 	{
1098 		.limits = wlan_hdd_sta_p2p_iface_limit,
1099 		.num_different_channels = 2,
1100 		.max_interfaces = 2,
1101 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
1102 		.beacon_int_infra_match = true,
1103 	},
1104 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
1105 	/* STA + SAP */
1106 	{
1107 		.limits = wlan_hdd_sta_ap_iface_limit,
1108 		.num_different_channels = 2,
1109 		.max_interfaces = 2,
1110 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
1111 		.beacon_int_infra_match = true,
1112 	},
1113 #endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
1114 	/* Monitor */
1115 	{
1116 		.limits = wlan_hdd_mon_iface_limit,
1117 		.max_interfaces = 2,
1118 		.num_different_channels = 2,
1119 		.n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
1120 	},
1121 #if defined(WLAN_FEATURE_NAN) && \
1122 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
1123 #ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
1124 	/* NAN + STA */
1125 	{
1126 		.limits = wlan_hdd_sta_nan_iface_limit,
1127 		.max_interfaces = 2,
1128 		.num_different_channels = 2,
1129 		.n_limits = ARRAY_SIZE(wlan_hdd_sta_nan_iface_limit),
1130 	},
1131 #endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
1132 #ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
1133 	/* NAN + SAP */
1134 	{
1135 		.limits = wlan_hdd_sap_nan_iface_limit,
1136 		.num_different_channels = 2,
1137 		.max_interfaces = 2,
1138 		.n_limits = ARRAY_SIZE(wlan_hdd_sap_nan_iface_limit),
1139 		.beacon_int_infra_match = true,
1140 	},
1141 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
1142 #endif /* WLAN_FEATURE_NAN */
1143 };
1144 static struct cfg80211_ops wlan_hdd_cfg80211_ops;
1145 
1146 #ifdef WLAN_NL80211_TESTMODE
1147 enum wlan_hdd_tm_attr {
1148 	WLAN_HDD_TM_ATTR_INVALID = 0,
1149 	WLAN_HDD_TM_ATTR_CMD = 1,
1150 	WLAN_HDD_TM_ATTR_DATA = 2,
1151 	WLAN_HDD_TM_ATTR_STREAM_ID = 3,
1152 	WLAN_HDD_TM_ATTR_TYPE = 4,
1153 	/* keep last */
1154 	WLAN_HDD_TM_ATTR_AFTER_LAST,
1155 	WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
1156 };
1157 
1158 enum wlan_hdd_tm_cmd {
1159 	WLAN_HDD_TM_CMD_WLAN_FTM = 0,
1160 	WLAN_HDD_TM_CMD_WLAN_HB = 1,
1161 };
1162 
1163 #define WLAN_HDD_TM_DATA_MAX_LEN    5000
1164 
1165 static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
1166 	[WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
1167 	[WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
1168 				   .len = WLAN_HDD_TM_DATA_MAX_LEN},
1169 };
1170 #endif /* WLAN_NL80211_TESTMODE */
1171 
1172 enum wlan_hdd_vendor_ie_access_policy {
1173 	WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
1174 	WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
1175 };
1176 
1177 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
1178 static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
1179 	.flags = WIPHY_WOWLAN_MAGIC_PKT,
1180 	.n_patterns = WOWL_MAX_PTRNS_ALLOWED,
1181 	.pattern_min_len = 1,
1182 	.pattern_max_len = WOWL_PTRN_MAX_SIZE,
1183 };
1184 #endif
1185 
1186 /**
1187  * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
1188  * @flags: Pointer to the flags to Add channel switch flag.
1189  *
1190  * This Function adds Channel Switch support flag, if channel switch is
1191  * supported by kernel.
1192  * Return: void.
1193  */
1194 #ifdef CHANNEL_SWITCH_SUPPORTED
1195 static inline void hdd_add_channel_switch_support(uint32_t *flags)
1196 {
1197 	*flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
1198 }
1199 #else
1200 static inline void hdd_add_channel_switch_support(uint32_t *flags)
1201 {
1202 }
1203 #endif
1204 
1205 #ifdef FEATURE_WLAN_TDLS
1206 
1207 /* TDLS capabilities params */
1208 #define PARAM_MAX_TDLS_SESSION \
1209 		QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
1210 #define PARAM_TDLS_FEATURE_SUPPORT \
1211 		QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
1212 
1213 /**
1214  * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
1215  * @wiphy:    WIPHY structure pointer
1216  * @wdev:     Wireless device structure pointer
1217  * @data:     Pointer to the data received
1218  * @data_len: Length of the data received
1219  *
1220  * This function provides TDLS capabilities
1221  *
1222  * Return: 0 on success and errno on failure
1223  */
1224 static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
1225 						     struct wireless_dev *wdev,
1226 						     const void *data,
1227 						     int data_len)
1228 {
1229 	int status;
1230 	struct net_device *dev = wdev->netdev;
1231 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1232 	struct wlan_objmgr_vdev *vdev;
1233 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
1234 	struct sk_buff *skb;
1235 	uint32_t set = 0;
1236 	uint32_t max_num_tdls_sta = 0;
1237 	bool tdls_support;
1238 	bool tdls_external_control;
1239 	bool tdls_sleep_sta_enable;
1240 	bool tdls_buffer_sta;
1241 	bool tdls_off_channel;
1242 	bool tdls_fw_wideband_cap;
1243 
1244 	hdd_enter_dev(wdev->netdev);
1245 
1246 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1247 		hdd_err("Command not allowed in FTM mode");
1248 		return -EPERM;
1249 	}
1250 
1251 	if (hdd_validate_adapter(adapter))
1252 		return -EINVAL;
1253 
1254 	status = wlan_hdd_validate_context(hdd_ctx);
1255 	if (status)
1256 		return status;
1257 
1258 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1259 						       (2 * sizeof(u32)) +
1260 						       NLMSG_HDRLEN);
1261 	if (!skb) {
1262 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1263 		goto fail;
1264 	}
1265 
1266 	if ((cfg_tdls_get_support_enable(hdd_ctx->psoc, &tdls_support) ==
1267 	     QDF_STATUS_SUCCESS) && !tdls_support) {
1268 		hdd_debug("TDLS feature not Enabled or Not supported in FW");
1269 		if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
1270 			nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
1271 			hdd_err("nla put fail");
1272 			goto fail;
1273 		}
1274 	} else {
1275 		cfg_tdls_get_external_control(hdd_ctx->psoc,
1276 					      &tdls_external_control);
1277 		cfg_tdls_get_sleep_sta_enable(hdd_ctx->psoc,
1278 					      &tdls_sleep_sta_enable);
1279 		cfg_tdls_get_buffer_sta_enable(hdd_ctx->psoc,
1280 					       &tdls_buffer_sta);
1281 		cfg_tdls_get_off_channel_enable(hdd_ctx->psoc,
1282 						&tdls_off_channel);
1283 		vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
1284 						   WLAN_OSIF_ID);
1285 		if (!vdev) {
1286 			hdd_err("Vdev is null return");
1287 			goto fail;
1288 		}
1289 
1290 		tdls_fw_wideband_cap =
1291 				wlan_cfg80211_tdls_is_fw_wideband_capable(vdev);
1292 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
1293 
1294 		set = set | WIFI_TDLS_SUPPORT;
1295 		set = set | (tdls_external_control ?
1296 					WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
1297 		set = set | (tdls_off_channel ?
1298 					WIFI_TDLS_OFFCHANNEL_SUPPORT : 0);
1299 		set = set | (tdls_fw_wideband_cap ?
1300 					WIFI_TDLS_WIDER_BW_SUPPORT : 0);
1301 		max_num_tdls_sta = cfg_tdls_get_max_peer_count(hdd_ctx->psoc);
1302 
1303 		hdd_debug("TDLS Feature supported value %x tdls_max_peer_count:%d",
1304 			  set, max_num_tdls_sta);
1305 		if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
1306 				max_num_tdls_sta) ||
1307 		    nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
1308 			hdd_err("nla put fail");
1309 			goto fail;
1310 		}
1311 	}
1312 	return wlan_cfg80211_vendor_cmd_reply(skb);
1313 fail:
1314 	wlan_cfg80211_vendor_free_skb(skb);
1315 	return -EINVAL;
1316 }
1317 
1318 /**
1319  * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
1320  * @wiphy:    WIPHY structure pointer
1321  * @wdev:     Wireless device structure pointer
1322  * @data:     Pointer to the data received
1323  * @data_len: Length of the data received
1324  *
1325  * This function provides TDLS capabilities
1326  *
1327  * Return: 0 on success and errno on failure
1328  */
1329 static int
1330 wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
1331 					struct wireless_dev *wdev,
1332 					const void *data,
1333 					int data_len)
1334 {
1335 	struct osif_psoc_sync *psoc_sync;
1336 	int errno;
1337 
1338 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
1339 	if (errno)
1340 		return errno;
1341 
1342 	errno = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
1343 							  data, data_len);
1344 
1345 	osif_psoc_sync_op_stop(psoc_sync);
1346 
1347 	return errno;
1348 }
1349 
1350 static uint8_t hdd_get_bw_offset(uint32_t ch_width)
1351 {
1352 	uint8_t bw_offset = 0;
1353 
1354 	if (ch_width == CH_WIDTH_40MHZ)
1355 		bw_offset = 1 << BW_40_OFFSET_BIT;
1356 	else if (ch_width == CH_WIDTH_20MHZ)
1357 		bw_offset = 1 << BW_20_OFFSET_BIT;
1358 
1359 	return bw_offset;
1360 }
1361 
1362 #else /* !FEATURE_WLAN_TDLS */
1363 
1364 static inline uint8_t hdd_get_bw_offset(uint32_t ch_width)
1365 {
1366 	return 0;
1367 }
1368 
1369 #endif /* FEATURE_WLAN_TDLS */
1370 
1371 /**
1372  * wlan_vendor_bitmap_to_reg_wifi_band_bitmap() - Convert vendor bitmap to
1373  * reg_wifi_band bitmap
1374  * @psoc: PSOC pointer
1375  * @vendor_bitmap: vendor bitmap value coming via vendor command
1376  *
1377  * Return: reg_wifi_band bitmap
1378  */
1379 static uint32_t
1380 wlan_vendor_bitmap_to_reg_wifi_band_bitmap(struct wlan_objmgr_psoc *psoc,
1381 					   uint32_t vendor_bitmap)
1382 {
1383 	uint32_t reg_bitmap = 0;
1384 
1385 	if (vendor_bitmap == QCA_SETBAND_AUTO)
1386 		reg_bitmap |= REG_BAND_MASK_ALL;
1387 	if (vendor_bitmap & QCA_SETBAND_2G)
1388 		reg_bitmap |= BIT(REG_BAND_2G);
1389 	if (vendor_bitmap & QCA_SETBAND_5G)
1390 		reg_bitmap |= BIT(REG_BAND_5G);
1391 	if (vendor_bitmap & QCA_SETBAND_6G)
1392 		reg_bitmap |= BIT(REG_BAND_6G);
1393 
1394 	if (!wlan_reg_is_6ghz_supported(psoc)) {
1395 		hdd_debug("Driver doesn't support 6ghz");
1396 		reg_bitmap = (reg_bitmap & (~BIT(REG_BAND_6G)));
1397 	}
1398 
1399 	return reg_bitmap;
1400 }
1401 
1402 int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
1403 		struct ch_avoid_ind_type *srcFreqList)
1404 {
1405 	int i;
1406 	uint32_t room;
1407 	struct ch_avoid_freq_type *avoid_range =
1408 	&destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
1409 
1410 	room = CH_AVOID_MAX_RANGE - destFreqList->ch_avoid_range_cnt;
1411 	if (srcFreqList->ch_avoid_range_cnt > room) {
1412 		hdd_err("avoid freq overflow");
1413 		return -EINVAL;
1414 	}
1415 	destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
1416 
1417 	for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
1418 		avoid_range->start_freq =
1419 			srcFreqList->avoid_freq_range[i].start_freq;
1420 		avoid_range->end_freq =
1421 			srcFreqList->avoid_freq_range[i].end_freq;
1422 		avoid_range++;
1423 	}
1424 	return 0;
1425 }
1426 /*
1427  * FUNCTION: wlan_hdd_send_avoid_freq_event
1428  * This is called when wlan driver needs to send vendor specific
1429  * avoid frequency range event to userspace
1430  */
1431 int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
1432 				   struct ch_avoid_ind_type *avoid_freq_list)
1433 {
1434 	struct sk_buff *skb;
1435 	enum qca_nl80211_vendor_subcmds_index index =
1436 		QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX;
1437 
1438 	hdd_enter();
1439 
1440 	if (!hdd_ctx) {
1441 		hdd_err("HDD context is null");
1442 		return -EINVAL;
1443 	}
1444 
1445 	if (!avoid_freq_list) {
1446 		hdd_err("avoid_freq_list is null");
1447 		return -EINVAL;
1448 	}
1449 
1450 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
1451 					       sizeof(struct ch_avoid_ind_type),
1452 					       index, GFP_KERNEL);
1453 	if (!skb) {
1454 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1455 		return -EINVAL;
1456 	}
1457 
1458 	memcpy(skb_put(skb, sizeof(struct ch_avoid_ind_type)),
1459 	       (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
1460 
1461 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
1462 
1463 	hdd_exit();
1464 	return 0;
1465 }
1466 
1467 /*
1468  * define short names for the global vendor params
1469  * used by QCA_NL80211_VENDOR_SUBCMD_HANG
1470  */
1471 #define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
1472 
1473 /**
1474  * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
1475  * hang reason
1476  * @reason: cds recovery reason
1477  *
1478  * Return: Vendor specific reason code
1479  */
1480 static enum qca_wlan_vendor_hang_reason
1481 hdd_convert_hang_reason(enum qdf_hang_reason reason)
1482 {
1483 	u32 ret_val;
1484 
1485 	switch (reason) {
1486 	case QDF_RX_HASH_NO_ENTRY_FOUND:
1487 		ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
1488 		break;
1489 	case QDF_PEER_DELETION_TIMEDOUT:
1490 		ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
1491 		break;
1492 	case QDF_PEER_UNMAP_TIMEDOUT:
1493 		ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
1494 		break;
1495 	case QDF_SCAN_REQ_EXPIRED:
1496 		ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
1497 		break;
1498 	case QDF_SCAN_ATTEMPT_FAILURES:
1499 		ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
1500 		break;
1501 	case QDF_GET_MSG_BUFF_FAILURE:
1502 		ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
1503 		break;
1504 	case QDF_ACTIVE_LIST_TIMEOUT:
1505 		ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
1506 		break;
1507 	case QDF_SUSPEND_TIMEOUT:
1508 		ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
1509 		break;
1510 	case QDF_RESUME_TIMEOUT:
1511 		ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
1512 		break;
1513 	case QDF_WMI_EXCEED_MAX_PENDING_CMDS:
1514 		ret_val = QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS;
1515 		break;
1516 	case QDF_AP_STA_CONNECT_REQ_TIMEOUT:
1517 		ret_val = QCA_WLAN_HANG_AP_STA_CONNECT_REQ_TIMEOUT;
1518 		break;
1519 	case QDF_STA_AP_CONNECT_REQ_TIMEOUT:
1520 		ret_val = QCA_WLAN_HANG_STA_AP_CONNECT_REQ_TIMEOUT;
1521 		break;
1522 	case QDF_MAC_HW_MODE_CHANGE_TIMEOUT:
1523 		ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CHANGE_TIMEOUT;
1524 		break;
1525 	case QDF_MAC_HW_MODE_CONFIG_TIMEOUT:
1526 		ret_val = QCA_WLAN_HANG_MAC_HW_MODE_CONFIG_TIMEOUT;
1527 		break;
1528 	case QDF_VDEV_START_RESPONSE_TIMED_OUT:
1529 		ret_val = QCA_WLAN_HANG_VDEV_START_RESPONSE_TIMED_OUT;
1530 		break;
1531 	case QDF_VDEV_RESTART_RESPONSE_TIMED_OUT:
1532 		ret_val = QCA_WLAN_HANG_VDEV_RESTART_RESPONSE_TIMED_OUT;
1533 		break;
1534 	case QDF_VDEV_STOP_RESPONSE_TIMED_OUT:
1535 		ret_val = QCA_WLAN_HANG_VDEV_STOP_RESPONSE_TIMED_OUT;
1536 		break;
1537 	case QDF_VDEV_DELETE_RESPONSE_TIMED_OUT:
1538 		ret_val = QCA_WLAN_HANG_VDEV_DELETE_RESPONSE_TIMED_OUT;
1539 		break;
1540 	case QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT:
1541 		ret_val = QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
1542 		break;
1543 	case QDF_WMI_BUF_SEQUENCE_MISMATCH:
1544 		ret_val = QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT;
1545 		break;
1546 	case QDF_HAL_REG_WRITE_FAILURE:
1547 		ret_val = QCA_WLAN_HANG_REG_WRITE_FAILURE;
1548 		break;
1549 	case QDF_SUSPEND_NO_CREDIT:
1550 		ret_val = QCA_WLAN_HANG_SUSPEND_NO_CREDIT;
1551 		break;
1552 	case QCA_HANG_BUS_FAILURE:
1553 		ret_val = QCA_WLAN_HANG_BUS_FAILURE;
1554 		break;
1555 	case QDF_TASKLET_CREDIT_LATENCY_DETECT:
1556 		ret_val = QCA_WLAN_HANG_TASKLET_CREDIT_LATENCY_DETECT;
1557 		break;
1558 	case QDF_RX_REG_PKT_ROUTE_ERR:
1559 		ret_val = QCA_WLAN_HANG_RX_MSDU_BUF_RCVD_IN_ERR_RING;
1560 		break;
1561 	case QDF_VDEV_SM_OUT_OF_SYNC:
1562 		ret_val = QCA_WLAN_HANG_VDEV_SM_OUT_OF_SYNC;
1563 		break;
1564 	case QDF_STATS_REQ_TIMEDOUT:
1565 		ret_val = QCA_WLAN_HANG_STATS_REQ_TIMEOUT;
1566 		break;
1567 	case QDF_TX_DESC_LEAK:
1568 		ret_val = QCA_WLAN_HANG_TX_DESC_LEAK;
1569 		break;
1570 	case QDF_SCHED_TIMEOUT:
1571 		ret_val = QCA_WLAN_HANG_SCHED_TIMEOUT;
1572 		break;
1573 	case QDF_SELF_PEER_DEL_FAILED:
1574 		ret_val = QCA_WLAN_HANG_SELF_PEER_DEL_FAIL;
1575 		break;
1576 	case QDF_DEL_SELF_STA_FAILED:
1577 		ret_val = QCA_WLAN_HANG_DEL_SELF_STA_FAIL;
1578 		break;
1579 	case QDF_FLUSH_LOGS:
1580 		ret_val = QCA_WLAN_HANG_FLUSH_LOGS;
1581 		break;
1582 	case QDF_HOST_WAKEUP_REASON_PAGEFAULT:
1583 		ret_val = QCA_WLAN_HANG_HOST_WAKEUP_REASON_PAGE_FAULT;
1584 		break;
1585 	case QDF_REASON_UNSPECIFIED:
1586 	default:
1587 		ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
1588 		break;
1589 	}
1590 	return ret_val;
1591 }
1592 
1593 /**
1594  * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
1595  * @hdd_ctx: Pointer to hdd context
1596  * @reason: cds recovery reason
1597  * @data: Hang Data
1598  * @data_len: length of @data
1599  *
1600  * Return: 0 on success or failure reason
1601  */
1602 int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
1603 				    enum qdf_hang_reason reason, uint8_t *data,
1604 				    size_t data_len)
1605 {
1606 	struct sk_buff *vendor_event;
1607 	enum qca_wlan_vendor_hang_reason hang_reason;
1608 
1609 	hdd_enter();
1610 
1611 	if (!hdd_ctx) {
1612 		hdd_err("HDD context is null");
1613 		return -EINVAL;
1614 	}
1615 
1616 	vendor_event = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1617 							NULL,
1618 							sizeof(uint32_t) +
1619 							data_len,
1620 							HANG_REASON_INDEX,
1621 							GFP_KERNEL);
1622 	if (!vendor_event) {
1623 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1624 		return -ENOMEM;
1625 	}
1626 
1627 	hang_reason = hdd_convert_hang_reason(reason);
1628 
1629 	if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
1630 			(uint32_t)hang_reason) ||
1631 	    nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON_DATA,
1632 		    data_len, data)) {
1633 		hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
1634 		wlan_cfg80211_vendor_free_skb(vendor_event);
1635 		return -EINVAL;
1636 	}
1637 
1638 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1639 
1640 	hdd_exit();
1641 	return 0;
1642 }
1643 
1644 #undef HANG_REASON_INDEX
1645 
1646 /**
1647  * wlan_hdd_get_adjacent_chan_freq(): Gets next/previous channel
1648  * with respect to the channel passed.
1649  * @freq: Channel frequency
1650  * @upper: If "true" then next channel is returned or else
1651  * previous channel is returned.
1652  *
1653  * This function returns the next/previous adjacent-channel to
1654  * the channel passed. If "upper = true" then next channel is
1655  * returned else previous is returned.
1656  */
1657 static qdf_freq_t wlan_hdd_get_adjacent_chan_freq(qdf_freq_t freq, bool upper)
1658 {
1659 	enum channel_enum ch_idx = wlan_reg_get_chan_enum_for_freq(freq);
1660 
1661 	if (reg_is_chan_enum_invalid(ch_idx))
1662 		return -EINVAL;
1663 
1664 	if (upper && (ch_idx < (NUM_CHANNELS - 1)))
1665 		ch_idx++;
1666 	else if (!upper && (ch_idx > CHAN_ENUM_2412))
1667 		ch_idx--;
1668 	else
1669 		return -EINVAL;
1670 
1671 	return WLAN_REG_CH_TO_FREQ(ch_idx);
1672 }
1673 
1674 /**
1675  * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
1676  * avoided when Do_Not_Break_Stream is active.
1677  * @hdd_ctx:  HDD Context
1678  * @op_freq:  AP/P2P-GO operating channel frequency
1679  *
1680  * This function sends list of frequencies to be avoided when
1681  * Do_Not_Break_Stream is active.
1682  * To clear the avoid_frequency_list in the application,
1683  * op_freq = 0 can be passed.
1684  *
1685  * Return: 0 on success and errno on failure
1686  */
1687 int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx,
1688 				      qdf_freq_t op_freq)
1689 {
1690 	struct ch_avoid_ind_type p2p_avoid_freq_list;
1691 	qdf_freq_t min_freq, max_freq;
1692 	int ret;
1693 	qdf_freq_t freq;
1694 
1695 	hdd_enter();
1696 
1697 	if (!hdd_ctx) {
1698 		hdd_err("invalid param");
1699 		return -EINVAL;
1700 	}
1701 
1702 	qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
1703 	/*
1704 	 * If channel passed is zero, clear the avoid_freq list in application.
1705 	 */
1706 	if (!op_freq) {
1707 #ifdef FEATURE_WLAN_CH_AVOID
1708 		mutex_lock(&hdd_ctx->avoid_freq_lock);
1709 		qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
1710 				sizeof(struct ch_avoid_ind_type));
1711 		if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
1712 			memcpy(&p2p_avoid_freq_list,
1713 			       &hdd_ctx->coex_avoid_freq_list,
1714 			       sizeof(struct ch_avoid_ind_type));
1715 		mutex_unlock(&hdd_ctx->avoid_freq_lock);
1716 #endif
1717 		ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
1718 						     &p2p_avoid_freq_list);
1719 		if (ret)
1720 			hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1721 				ret);
1722 
1723 		return ret;
1724 	}
1725 
1726 	if (WLAN_REG_IS_24GHZ_CH_FREQ(op_freq)) {
1727 		min_freq = WLAN_REG_MIN_24GHZ_CHAN_FREQ;
1728 		max_freq = WLAN_REG_MAX_24GHZ_CHAN_FREQ;
1729 	} else if (WLAN_REG_IS_5GHZ_CH_FREQ(op_freq)) {
1730 		min_freq = WLAN_REG_MIN_5GHZ_CHAN_FREQ;
1731 		max_freq = WLAN_REG_MAX_5GHZ_CHAN_FREQ;
1732 	} else {
1733 		hdd_err("invalid channel freq:%d", op_freq);
1734 		return -EINVAL;
1735 	}
1736 
1737 	if (op_freq > min_freq && op_freq < max_freq) {
1738 		p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1739 		p2p_avoid_freq_list.avoid_freq_range[0].start_freq = min_freq;
1740 
1741 		/* Get channel before the op_freq */
1742 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, false);
1743 		if (freq < 0)
1744 			return -EINVAL;
1745 		p2p_avoid_freq_list.avoid_freq_range[0].end_freq = freq;
1746 
1747 		/* Get channel next to the op_freq */
1748 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, true);
1749 		if (freq < 0)
1750 			return -EINVAL;
1751 		p2p_avoid_freq_list.avoid_freq_range[1].start_freq = freq;
1752 
1753 		p2p_avoid_freq_list.avoid_freq_range[1].end_freq = max_freq;
1754 	} else if (op_freq == min_freq) {
1755 		p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1756 
1757 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, true);
1758 		if (freq < 0)
1759 			return -EINVAL;
1760 		p2p_avoid_freq_list.avoid_freq_range[0].start_freq = freq;
1761 
1762 		p2p_avoid_freq_list.avoid_freq_range[0].end_freq = max_freq;
1763 	} else {
1764 		p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1765 		p2p_avoid_freq_list.avoid_freq_range[0].start_freq = min_freq;
1766 
1767 		freq = wlan_hdd_get_adjacent_chan_freq(op_freq, false);
1768 		if (freq < 0)
1769 			return -EINVAL;
1770 		p2p_avoid_freq_list.avoid_freq_range[0].end_freq = freq;
1771 	}
1772 #ifdef FEATURE_WLAN_CH_AVOID
1773 	mutex_lock(&hdd_ctx->avoid_freq_lock);
1774 	hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1775 	if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
1776 		ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
1777 				&hdd_ctx->coex_avoid_freq_list);
1778 		if (ret) {
1779 			mutex_unlock(&hdd_ctx->avoid_freq_lock);
1780 			hdd_err("avoid freq merge failed");
1781 			return ret;
1782 		}
1783 	}
1784 	mutex_unlock(&hdd_ctx->avoid_freq_lock);
1785 #endif
1786 	ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
1787 	if (ret)
1788 		hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1789 
1790 	return ret;
1791 }
1792 
1793 /* vendor specific events */
1794 static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
1795 	[QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1796 		.vendor_id =
1797 			QCA_NL80211_VENDOR_ID,
1798 		.subcmd =
1799 			QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1800 	},
1801 
1802 	[QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1803 		.vendor_id =
1804 			QCA_NL80211_VENDOR_ID,
1805 		.subcmd =
1806 			QCA_NL80211_VENDOR_SUBCMD_NAN
1807 	},
1808 
1809 #ifdef WLAN_FEATURE_STATS_EXT
1810 	[QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1811 		.vendor_id =
1812 			QCA_NL80211_VENDOR_ID,
1813 		.subcmd =
1814 			QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1815 	},
1816 #endif /* WLAN_FEATURE_STATS_EXT */
1817 	[QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS_INDEX] = {
1818 		.vendor_id =
1819 			QCA_NL80211_VENDOR_ID,
1820 		.subcmd =
1821 			QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS
1822 	},
1823 
1824 #ifdef FEATURE_WLAN_EXTSCAN
1825 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1826 		.vendor_id =
1827 			QCA_NL80211_VENDOR_ID,
1828 		.subcmd =
1829 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1830 	},
1831 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1832 		.vendor_id =
1833 			QCA_NL80211_VENDOR_ID,
1834 		.subcmd =
1835 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1836 	},
1837 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1838 		.
1839 		vendor_id
1840 			=
1841 				QCA_NL80211_VENDOR_ID,
1842 		.subcmd =
1843 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1844 	},
1845 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1846 		.
1847 		vendor_id
1848 			=
1849 				QCA_NL80211_VENDOR_ID,
1850 		.
1851 		subcmd =
1852 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1853 	},
1854 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1855 		.
1856 		vendor_id
1857 			=
1858 				QCA_NL80211_VENDOR_ID,
1859 		.
1860 		subcmd
1861 			=
1862 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1863 	},
1864 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1865 		.
1866 		vendor_id
1867 			=
1868 				QCA_NL80211_VENDOR_ID,
1869 		.subcmd =
1870 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1871 	},
1872 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1873 		.vendor_id =
1874 			QCA_NL80211_VENDOR_ID,
1875 		.subcmd =
1876 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1877 	},
1878 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1879 		.
1880 		vendor_id
1881 			=
1882 				QCA_NL80211_VENDOR_ID,
1883 		.subcmd =
1884 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1885 	},
1886 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1887 		.
1888 		vendor_id
1889 			=
1890 				QCA_NL80211_VENDOR_ID,
1891 		.subcmd =
1892 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1893 	},
1894 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1895 		.
1896 		vendor_id
1897 			=
1898 				QCA_NL80211_VENDOR_ID,
1899 		.
1900 		subcmd
1901 			=
1902 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1903 	},
1904 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1905 		.
1906 		vendor_id
1907 			=
1908 				QCA_NL80211_VENDOR_ID,
1909 		.
1910 		subcmd =
1911 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1912 	},
1913 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1914 		.
1915 		vendor_id
1916 			=
1917 				QCA_NL80211_VENDOR_ID,
1918 		.
1919 		subcmd
1920 			=
1921 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1922 	},
1923 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1924 		.
1925 		vendor_id
1926 			=
1927 				QCA_NL80211_VENDOR_ID,
1928 		.
1929 		subcmd
1930 			=
1931 				QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1932 	},
1933 #endif /* FEATURE_WLAN_EXTSCAN */
1934 
1935 #ifdef WLAN_FEATURE_LINK_LAYER_STATS
1936 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1937 		.vendor_id =
1938 			QCA_NL80211_VENDOR_ID,
1939 		.subcmd =
1940 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1941 	},
1942 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1943 		.vendor_id =
1944 			QCA_NL80211_VENDOR_ID,
1945 		.subcmd =
1946 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1947 	},
1948 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1949 		.vendor_id =
1950 			QCA_NL80211_VENDOR_ID,
1951 		.subcmd =
1952 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1953 	},
1954 	[QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1955 		.vendor_id =
1956 			QCA_NL80211_VENDOR_ID,
1957 		.subcmd =
1958 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1959 	},
1960 	[QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1961 		.vendor_id =
1962 			QCA_NL80211_VENDOR_ID,
1963 		.subcmd =
1964 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1965 	},
1966 	[QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1967 		.vendor_id =
1968 			QCA_NL80211_VENDOR_ID,
1969 		.subcmd =
1970 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1971 	},
1972 	[QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1973 		.vendor_id =
1974 			QCA_NL80211_VENDOR_ID,
1975 		.subcmd =
1976 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1977 	},
1978 #endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1979 	[QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1980 		.vendor_id =
1981 			QCA_NL80211_VENDOR_ID,
1982 		.subcmd =
1983 			QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1984 	},
1985 	[QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1986 		.vendor_id = QCA_NL80211_VENDOR_ID,
1987 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1988 	},
1989 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
1990 	[QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1991 		.vendor_id =
1992 			QCA_NL80211_VENDOR_ID,
1993 		.subcmd =
1994 			QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1995 	},
1996 #endif
1997 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] =  {
1998 		.vendor_id =
1999 			QCA_NL80211_VENDOR_ID,
2000 		.subcmd =
2001 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
2002 	},
2003 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] =  {
2004 		.vendor_id =
2005 			QCA_NL80211_VENDOR_ID,
2006 		.subcmd =
2007 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
2008 	},
2009 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] =  {
2010 		.vendor_id =
2011 			QCA_NL80211_VENDOR_ID,
2012 		.subcmd =
2013 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
2014 	},
2015 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] =  {
2016 		.vendor_id =
2017 			QCA_NL80211_VENDOR_ID,
2018 		.subcmd =
2019 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
2020 	},
2021 	[QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] =  {
2022 		.vendor_id =
2023 			QCA_NL80211_VENDOR_ID,
2024 		.subcmd =
2025 			QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
2026 	},
2027 #ifdef FEATURE_WLAN_EXTSCAN
2028 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
2029 		.vendor_id = QCA_NL80211_VENDOR_ID,
2030 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
2031 	},
2032 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
2033 		.vendor_id = QCA_NL80211_VENDOR_ID,
2034 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
2035 	},
2036 	[QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
2037 		.vendor_id = QCA_NL80211_VENDOR_ID,
2038 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
2039 	},
2040 #endif /* FEATURE_WLAN_EXTSCAN */
2041 
2042 	FEATURE_RSSI_MONITOR_VENDOR_EVENTS
2043 
2044 #ifdef WLAN_FEATURE_TSF
2045 	[QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
2046 		.vendor_id = QCA_NL80211_VENDOR_ID,
2047 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
2048 	},
2049 #endif
2050 	[QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
2051 		.vendor_id = QCA_NL80211_VENDOR_ID,
2052 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
2053 	},
2054 	[QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
2055 		.vendor_id = QCA_NL80211_VENDOR_ID,
2056 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
2057 	},
2058 	/* OCB events */
2059 	[QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
2060 		.vendor_id = QCA_NL80211_VENDOR_ID,
2061 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
2062 	},
2063 #ifdef FEATURE_LFR_SUBNET_DETECTION
2064 	[QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
2065 		.vendor_id = QCA_NL80211_VENDOR_ID,
2066 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
2067 	},
2068 #endif /*FEATURE_LFR_SUBNET_DETECTION */
2069 
2070 	FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS_INDEX
2071 
2072 	[QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
2073 		.vendor_id = QCA_NL80211_VENDOR_ID,
2074 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
2075 	},
2076 
2077 	[QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
2078 		.vendor_id = QCA_NL80211_VENDOR_ID,
2079 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
2080 	},
2081 	[QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
2082 		.vendor_id = QCA_NL80211_VENDOR_ID,
2083 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
2084 	},
2085 	[QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
2086 		.vendor_id = QCA_NL80211_VENDOR_ID,
2087 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
2088 	},
2089 	[QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
2090 		.vendor_id = QCA_NL80211_VENDOR_ID,
2091 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
2092 	},
2093 	[QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
2094 		.vendor_id = QCA_NL80211_VENDOR_ID,
2095 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
2096 	},
2097 	[QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
2098 		.vendor_id = QCA_NL80211_VENDOR_ID,
2099 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
2100 	},
2101 	[QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
2102 		.vendor_id = QCA_NL80211_VENDOR_ID,
2103 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
2104 	},
2105 	[QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX] = {
2106 		.vendor_id = QCA_NL80211_VENDOR_ID,
2107 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT,
2108 	 },
2109 	[QCA_NL80211_VENDOR_SUBCMD_NAN_EXT_INDEX] = {
2110 		.vendor_id = QCA_NL80211_VENDOR_ID,
2111 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN_EXT
2112 	},
2113 	[QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX] = {
2114 		.vendor_id = QCA_NL80211_VENDOR_ID,
2115 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
2116 	},
2117 
2118 	BCN_RECV_FEATURE_VENDOR_EVENTS
2119 	FEATURE_MEDIUM_ASSESS_VENDOR_EVENTS
2120 	[QCA_NL80211_VENDOR_SUBCMD_ROAM_INDEX] = {
2121 		.vendor_id = QCA_NL80211_VENDOR_ID,
2122 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
2123 	},
2124 	[QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX] = {
2125 		.vendor_id = QCA_NL80211_VENDOR_ID,
2126 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_OEM_DATA,
2127 	},
2128 	[QCA_NL80211_VENDOR_SUBCMD_REQUEST_SAR_LIMITS_INDEX] = {
2129 		.vendor_id = QCA_NL80211_VENDOR_ID,
2130 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS_EVENT,
2131 	},
2132 	[QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX] = {
2133 		.vendor_id = QCA_NL80211_VENDOR_ID,
2134 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO,
2135 	},
2136 	FEATURE_THERMAL_VENDOR_EVENTS
2137 	FEATURE_DRIVER_DISCONNECT_REASON
2138 #ifdef WLAN_SUPPORT_TWT
2139 	FEATURE_TWT_VENDOR_EVENTS
2140 #endif
2141 	FEATURE_CFR_DATA_VENDOR_EVENTS
2142 #ifdef WLAN_FEATURE_CONNECTIVITY_LOGGING
2143 	FEATURE_CONNECTIVITY_LOGGING_EVENT
2144 #endif
2145 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
2146 	[QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS_INDEX] = {
2147 		.vendor_id = QCA_NL80211_VENDOR_ID,
2148 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS,
2149 	},
2150 #endif
2151 	FEATURE_MCC_QUOTA_VENDOR_EVENTS
2152 	[QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY_INDEX] = {
2153 		.vendor_id = QCA_NL80211_VENDOR_ID,
2154 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_DRIVER_READY,
2155 	},
2156 	FEATURE_WIFI_POS_11AZ_AUTH_EVENTS
2157 #ifdef WLAN_FEATURE_SR
2158 	[QCA_NL80211_VENDOR_SUBCMD_SR_INDEX] = {
2159 		.vendor_id = QCA_NL80211_VENDOR_ID,
2160 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_SR,
2161 	},
2162 #endif
2163 	FEATURE_GREEN_AP_LOW_LATENCY_PWR_SAVE_EVENT
2164 	FEATURE_ROAM_STATS_EVENTS
2165 #ifdef WLAN_FEATURE_11BE_MLO
2166 	[QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP_INDEX] = {
2167 		.vendor_id = QCA_NL80211_VENDOR_ID,
2168 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_TID_TO_LINK_MAP,
2169 	},
2170 	[QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG_INDEX] = {
2171 		.vendor_id = QCA_NL80211_VENDOR_ID,
2172 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_RECONFIG,
2173 	},
2174 #endif
2175 	FEATURE_AFC_VENDOR_EVENTS
2176 
2177 	[QCA_NL80211_VENDOR_SUBCMD_AUDIO_TRANSPORT_SWITCH_INDEX] = {
2178 		.vendor_id = QCA_NL80211_VENDOR_ID,
2179 		.subcmd = QCA_NL80211_VENDOR_SUBCMD_AUDIO_TRANSPORT_SWITCH,
2180 	},
2181 
2182 	FEATURE_TX_LATENCY_STATS_EVENTS
2183 };
2184 
2185 /**
2186  * __is_driver_dfs_capable() - get driver DFS capability
2187  * @wiphy:   pointer to wireless wiphy structure.
2188  * @wdev:    pointer to wireless_dev structure.
2189  * @data:    Pointer to the data to be passed via vendor interface
2190  * @data_len:Length of the data to be passed
2191  *
2192  * This function is called by userspace to indicate whether or not
2193  * the driver supports DFS offload.
2194  *
2195  * Return: 0 on success, negative errno on failure
2196  */
2197 static int __is_driver_dfs_capable(struct wiphy *wiphy,
2198 				   struct wireless_dev *wdev,
2199 				   const void *data,
2200 				   int data_len)
2201 {
2202 	u32 dfs_capability = 0;
2203 	struct sk_buff *temp_skbuff;
2204 	int ret_val;
2205 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
2206 
2207 	hdd_enter_dev(wdev->netdev);
2208 
2209 	ret_val = wlan_hdd_validate_context(hdd_ctx);
2210 	if (ret_val)
2211 		return ret_val;
2212 
2213 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2214 		hdd_err("Command not allowed in FTM mode");
2215 		return -EPERM;
2216 	}
2217 
2218 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
2219 	defined(CFG80211_DFS_OFFLOAD_BACKPORT)
2220 	dfs_capability =
2221 		wiphy_ext_feature_isset(wiphy,
2222 					NL80211_EXT_FEATURE_DFS_OFFLOAD);
2223 #else
2224 	dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
2225 #endif
2226 
2227 	temp_skbuff = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2228 							       sizeof(u32) +
2229 							       NLMSG_HDRLEN);
2230 	if (temp_skbuff) {
2231 		ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
2232 				      dfs_capability);
2233 		if (ret_val) {
2234 			hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
2235 			wlan_cfg80211_vendor_free_skb(temp_skbuff);
2236 
2237 			return ret_val;
2238 		}
2239 
2240 		return wlan_cfg80211_vendor_cmd_reply(temp_skbuff);
2241 	}
2242 
2243 	hdd_err("dfs capability: buffer alloc fail");
2244 	return -ENOMEM;
2245 }
2246 
2247 /**
2248  * is_driver_dfs_capable() - get driver DFS capability
2249  * @wiphy:   pointer to wireless wiphy structure.
2250  * @wdev:    pointer to wireless_dev structure.
2251  * @data:    Pointer to the data to be passed via vendor interface
2252  * @data_len:Length of the data to be passed
2253  *
2254  * This function is called by userspace to indicate whether or not
2255  * the driver supports DFS offload.  This is an SSR-protected
2256  * wrapper function.
2257  *
2258  * Return: 0 on success, negative errno on failure
2259  */
2260 static int is_driver_dfs_capable(struct wiphy *wiphy,
2261 				 struct wireless_dev *wdev,
2262 				 const void *data,
2263 				 int data_len)
2264 {
2265 	struct osif_psoc_sync *psoc_sync;
2266 	int errno;
2267 
2268 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
2269 	if (errno)
2270 		return errno;
2271 
2272 	errno = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
2273 
2274 	osif_psoc_sync_op_stop(psoc_sync);
2275 
2276 	return errno;
2277 }
2278 
2279 /**
2280  * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
2281  *
2282  * @adapter: SAP adapter pointer
2283  *
2284  * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
2285  * radio. So in case of DFS MCC scenario override current SAP given config
2286  * to follow concurrent SAP DFS config
2287  *
2288  * Return: 0 - No DFS issue, 1 - Override done and negative error codes
2289  */
2290 int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
2291 {
2292 	struct hdd_adapter *con_sap_adapter;
2293 	struct sap_config *sap_config, *con_sap_config;
2294 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2295 	uint32_t con_ch_freq;
2296 
2297 	if (!hdd_ctx) {
2298 		hdd_err("hdd context is NULL");
2299 		return 0;
2300 	}
2301 
2302 	/*
2303 	 * Check if AP+AP case, once primary AP chooses a DFS
2304 	 * channel secondary AP should always follow primary APs channel
2305 	 */
2306 	if (!policy_mgr_concurrent_beaconing_sessions_running(
2307 		hdd_ctx->psoc))
2308 		return 0;
2309 
2310 	con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
2311 	if (!con_sap_adapter)
2312 		return 0;
2313 
2314 	sap_config = &adapter->deflink->session.ap.sap_config;
2315 	con_sap_config = &con_sap_adapter->deflink->session.ap.sap_config;
2316 	con_ch_freq = con_sap_adapter->deflink->session.ap.operating_chan_freq;
2317 
2318 	if (!wlan_reg_is_dfs_for_freq(hdd_ctx->pdev, con_ch_freq))
2319 		return 0;
2320 
2321 	hdd_debug("Only SCC AP-AP DFS Permitted (ch_freq=%d, con_ch_freq=%d)",
2322 		  sap_config->chan_freq, con_ch_freq);
2323 	hdd_debug("Overriding guest AP's channel");
2324 	sap_config->chan_freq = con_ch_freq;
2325 
2326 	if (con_sap_config->acs_cfg.acs_mode == true) {
2327 		if (con_ch_freq != con_sap_config->acs_cfg.pri_ch_freq &&
2328 		    con_ch_freq != con_sap_config->acs_cfg.ht_sec_ch_freq) {
2329 			hdd_err("Primary AP channel config error");
2330 			hdd_err("Operating ch: %d ACS ch freq: %d Sec Freq %d",
2331 				con_ch_freq,
2332 				con_sap_config->acs_cfg.pri_ch_freq,
2333 				con_sap_config->acs_cfg.ht_sec_ch_freq);
2334 			return -EINVAL;
2335 		}
2336 		/* Sec AP ACS info is overwritten with Pri AP due to DFS
2337 		 * MCC restriction. So free ch list allocated in do_acs
2338 		 * func for Sec AP and realloc for Pri AP ch list size
2339 		 */
2340 		if (sap_config->acs_cfg.freq_list) {
2341 			qdf_mem_free(sap_config->acs_cfg.freq_list);
2342 			sap_config->acs_cfg.freq_list = NULL;
2343 		}
2344 		if (sap_config->acs_cfg.master_freq_list) {
2345 			qdf_mem_free(sap_config->acs_cfg.master_freq_list);
2346 			sap_config->acs_cfg.master_freq_list = NULL;
2347 		}
2348 
2349 		qdf_mem_copy(&sap_config->acs_cfg,
2350 			     &con_sap_config->acs_cfg,
2351 			     sizeof(struct sap_acs_cfg));
2352 
2353 		sap_config->acs_cfg.freq_list =
2354 			qdf_mem_malloc(sizeof(uint32_t) *
2355 				con_sap_config->acs_cfg.ch_list_count);
2356 		if (!sap_config->acs_cfg.freq_list) {
2357 			sap_config->acs_cfg.ch_list_count = 0;
2358 			return -ENOMEM;
2359 		}
2360 		qdf_mem_copy(sap_config->acs_cfg.freq_list,
2361 			     con_sap_config->acs_cfg.freq_list,
2362 			     con_sap_config->acs_cfg.ch_list_count *
2363 				sizeof(uint32_t));
2364 
2365 		sap_config->acs_cfg.master_freq_list =
2366 			qdf_mem_malloc(sizeof(uint32_t) *
2367 				con_sap_config->acs_cfg.master_ch_list_count);
2368 		if (!sap_config->acs_cfg.master_freq_list) {
2369 			sap_config->acs_cfg.master_ch_list_count = 0;
2370 			qdf_mem_free(sap_config->acs_cfg.freq_list);
2371 			sap_config->acs_cfg.freq_list = NULL;
2372 			return -ENOMEM;
2373 		}
2374 		qdf_mem_copy(sap_config->acs_cfg.master_freq_list,
2375 			     con_sap_config->acs_cfg.master_freq_list,
2376 			     con_sap_config->acs_cfg.master_ch_list_count *
2377 				sizeof(uint32_t));
2378 	} else {
2379 		sap_config->acs_cfg.pri_ch_freq = con_ch_freq;
2380 		if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
2381 			sap_config->acs_cfg.ht_sec_ch_freq =
2382 						con_sap_config->sec_ch_freq;
2383 	}
2384 
2385 	return con_ch_freq;
2386 }
2387 
2388 /**
2389  * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
2390  * @sap_cfg: pointer to SAP config struct
2391  * @hw_mode: hw mode retrieved from vendor command buffer
2392  * @ht_enabled: whether HT phy mode is enabled
2393  * @vht_enabled: whether VHT phy mode is enabled
2394  *
2395  * This function populates the ACS hw mode based on the configuration retrieved
2396  * from the vendor command buffer; and sets ACS start and end channel for the
2397  * given band.
2398  *
2399  * Return: 0 if success; -EINVAL if ACS channel list is NULL
2400  */
2401 static int wlan_hdd_set_acs_ch_range(
2402 	struct sap_config *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
2403 	bool ht_enabled, bool vht_enabled)
2404 {
2405 	int i;
2406 
2407 	if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
2408 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
2409 		sap_cfg->acs_cfg.start_ch_freq =
2410 				wlan_reg_ch_to_freq(CHAN_ENUM_2412);
2411 		sap_cfg->acs_cfg.end_ch_freq =
2412 				wlan_reg_ch_to_freq(CHAN_ENUM_2484);
2413 	} else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
2414 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
2415 		sap_cfg->acs_cfg.start_ch_freq =
2416 				wlan_reg_ch_to_freq(CHAN_ENUM_2412);
2417 		sap_cfg->acs_cfg.end_ch_freq =
2418 				wlan_reg_ch_to_freq(CHAN_ENUM_2472);
2419 	} else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
2420 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
2421 		sap_cfg->acs_cfg.start_ch_freq =
2422 				wlan_reg_ch_to_freq(CHAN_ENUM_5180);
2423 		sap_cfg->acs_cfg.end_ch_freq =
2424 				wlan_reg_ch_to_freq(CHAN_ENUM_5885);
2425 	} else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
2426 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
2427 		sap_cfg->acs_cfg.start_ch_freq =
2428 				wlan_reg_ch_to_freq(CHAN_ENUM_2412);
2429 		sap_cfg->acs_cfg.end_ch_freq =
2430 				wlan_reg_ch_to_freq(CHAN_ENUM_5885);
2431 	}
2432 
2433 	if (ht_enabled)
2434 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
2435 
2436 	if (vht_enabled)
2437 		sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2438 
2439 	/* Parse ACS Chan list from hostapd */
2440 	if (!sap_cfg->acs_cfg.freq_list)
2441 		return -EINVAL;
2442 
2443 	sap_cfg->acs_cfg.start_ch_freq = sap_cfg->acs_cfg.freq_list[0];
2444 	sap_cfg->acs_cfg.end_ch_freq =
2445 		sap_cfg->acs_cfg.freq_list[sap_cfg->acs_cfg.ch_list_count - 1];
2446 	for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
2447 		/* avoid channel as start channel */
2448 		if (sap_cfg->acs_cfg.start_ch_freq >
2449 		    sap_cfg->acs_cfg.freq_list[i] &&
2450 		    sap_cfg->acs_cfg.freq_list[i] != 0)
2451 			sap_cfg->acs_cfg.start_ch_freq =
2452 			    sap_cfg->acs_cfg.freq_list[i];
2453 		if (sap_cfg->acs_cfg.end_ch_freq <
2454 				sap_cfg->acs_cfg.freq_list[i])
2455 			sap_cfg->acs_cfg.end_ch_freq =
2456 			    sap_cfg->acs_cfg.freq_list[i];
2457 	}
2458 
2459 	return 0;
2460 }
2461 
2462 static void hdd_update_acs_channel_list(struct sap_config *sap_config,
2463 					enum band_info band)
2464 {
2465 	int i, temp_count = 0;
2466 	int acs_list_count = sap_config->acs_cfg.ch_list_count;
2467 
2468 	for (i = 0; i < acs_list_count; i++) {
2469 		if (BAND_2G == band) {
2470 			if (WLAN_REG_IS_24GHZ_CH_FREQ(
2471 				sap_config->acs_cfg.freq_list[i])) {
2472 				sap_config->acs_cfg.freq_list[temp_count] =
2473 					sap_config->acs_cfg.freq_list[i];
2474 				temp_count++;
2475 			}
2476 		} else if (BAND_5G == band) {
2477 			if (WLAN_REG_IS_5GHZ_CH_FREQ(
2478 				sap_config->acs_cfg.freq_list[i]) ||
2479 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(
2480 				sap_config->acs_cfg.freq_list[i])) {
2481 				sap_config->acs_cfg.freq_list[temp_count] =
2482 					sap_config->acs_cfg.freq_list[i];
2483 				temp_count++;
2484 			}
2485 		}
2486 	}
2487 	sap_config->acs_cfg.ch_list_count = temp_count;
2488 }
2489 
2490 /**
2491  * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
2492  * @link_info: Link info pointer in SAP HDD adapter
2493  *
2494  * This function starts the ACS procedure if there are no
2495  * constraints like MBSSID DFS restrictions.
2496  *
2497  * Return: Status of ACS Start procedure
2498  */
2499 int wlan_hdd_cfg80211_start_acs(struct wlan_hdd_link_info *link_info)
2500 {
2501 	struct hdd_context *hdd_ctx;
2502 	struct sap_config *sap_config;
2503 	struct sap_context *sap_ctx;
2504 	struct hdd_ap_ctx *ap_ctx;
2505 	sap_event_cb acs_event_callback;
2506 	uint8_t mcc_to_scc_switch = 0;
2507 	int status;
2508 	QDF_STATUS qdf_status;
2509 	struct hdd_adapter *adapter = link_info->adapter;
2510 
2511 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2512 	status = wlan_hdd_validate_context(hdd_ctx);
2513 	if (0 != status)
2514 		return status;
2515 
2516 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
2517 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
2518 	sap_config = &ap_ctx->sap_config;
2519 
2520 	if (hdd_ctx->acs_policy.acs_chan_freq)
2521 		sap_config->chan_freq = hdd_ctx->acs_policy.acs_chan_freq;
2522 	else
2523 		sap_config->chan_freq = AUTO_CHANNEL_SELECT;
2524 	ucfg_policy_mgr_get_mcc_scc_switch(hdd_ctx->psoc,
2525 					   &mcc_to_scc_switch);
2526 	/*
2527 	 * No DFS SCC is allowed in Auto use case. Hence not
2528 	 * calling DFS override
2529 	 */
2530 	if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
2531 	    mcc_to_scc_switch &&
2532 	    !(policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) &&
2533 	    WLAN_REG_IS_24GHZ_CH_FREQ(sap_config->acs_cfg.end_ch_freq)) &&
2534 	    !wlansap_dcs_is_wlan_interference_mitigation_enabled(sap_ctx)) {
2535 		status = wlan_hdd_sap_cfg_dfs_override(adapter);
2536 		if (status < 0)
2537 			return status;
2538 
2539 		if (status > 0) {
2540 			/*notify hostapd about channel override */
2541 			wlan_hdd_cfg80211_acs_ch_select_evt(link_info, true);
2542 			wlansap_dcs_set_wlan_interference_mitigation_on_band(sap_ctx,
2543 									     sap_config);
2544 			return 0;
2545 		}
2546 	}
2547 	/* When first 2 connections are on the same frequency band,
2548 	 * then PCL would include only channels from the other
2549 	 * frequency band on which no connections are active
2550 	 */
2551 	if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
2552 		(sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2553 		struct policy_mgr_conc_connection_info *conc_connection_info;
2554 		uint32_t i;
2555 
2556 		conc_connection_info = policy_mgr_get_conn_info(&i);
2557 		if (policy_mgr_are_2_freq_on_same_mac(hdd_ctx->psoc,
2558 			conc_connection_info[0].freq,
2559 			conc_connection_info[1].freq)) {
2560 			if (!WLAN_REG_IS_24GHZ_CH_FREQ(
2561 				sap_config->acs_cfg.pcl_chan_freq[0])) {
2562 				sap_config->acs_cfg.band =
2563 					QCA_ACS_MODE_IEEE80211A;
2564 				hdd_update_acs_channel_list(sap_config,
2565 					BAND_5G);
2566 			} else {
2567 				sap_config->acs_cfg.band =
2568 					QCA_ACS_MODE_IEEE80211G;
2569 				hdd_update_acs_channel_list(sap_config,
2570 					BAND_2G);
2571 			}
2572 		}
2573 	}
2574 	status = wlan_hdd_config_acs(hdd_ctx, adapter);
2575 	if (status) {
2576 		hdd_err("ACS config failed");
2577 		return -EINVAL;
2578 	}
2579 
2580 	acs_event_callback = hdd_hostapd_sap_event_cb;
2581 
2582 	qdf_mem_copy(sap_config->self_macaddr.bytes,
2583 		adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
2584 
2585 	qdf_status = wlansap_acs_chselect(sap_ctx, acs_event_callback,
2586 					  sap_config, adapter->dev);
2587 
2588 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
2589 		hdd_err("ACS channel select failed");
2590 		return -EINVAL;
2591 	}
2592 	if (sap_is_auto_channel_select(sap_ctx))
2593 		sap_config->acs_cfg.acs_mode = true;
2594 
2595 	/* If ACS scan is skipped then ACS request would be completed by now,
2596 	 * so no need to set acs in progress
2597 	 */
2598 	if (!sap_config->acs_cfg.skip_acs_scan)
2599 		qdf_atomic_set(&ap_ctx->acs_in_progress, 1);
2600 
2601 	return 0;
2602 }
2603 
2604 /**
2605  * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
2606  * @hdd_ctx: hdd context
2607  * @acs_chan_params: external acs channel params
2608  * @sap_config: SAP config
2609  *
2610  * This API provides unsorted pcl list.
2611  * this list is a subset of the valid channel list given by hostapd.
2612  * if channel is not present in pcl, weightage will be given as zero
2613  *
2614  * Return: Zero on success, non-zero on failure
2615  */
2616 static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
2617 		struct hdd_vendor_acs_chan_params *acs_chan_params,
2618 		struct sap_config *sap_config)
2619 {
2620 	int i, j;
2621 	/*
2622 	 * PCL shall contain only the preferred channels from the
2623 	 * application. If those channels are not present in the
2624 	 * driver PCL, then set the weight to zero
2625 	 */
2626 	for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
2627 		acs_chan_params->vendor_pcl_list[i] =
2628 				sap_config->acs_cfg.freq_list[i];
2629 		acs_chan_params->vendor_weight_list[i] = 0;
2630 		for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
2631 			if (sap_config->acs_cfg.freq_list[i] ==
2632 			    sap_config->acs_cfg.pcl_chan_freq[j]) {
2633 				acs_chan_params->vendor_weight_list[i] =
2634 				sap_config->acs_cfg.pcl_channels_weight_list[j];
2635 				break;
2636 			}
2637 		}
2638 	}
2639 	acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
2640 }
2641 
2642 /**
2643  * hdd_update_reg_chan_info : This API constructs channel info
2644  * for all the given channel
2645  * @adapter: pointer to SAP adapter struct
2646  * @channel_count: channel count
2647  * @freq_list: channel frequency (MHz) list
2648  *
2649  * Return: Status of of channel information updation
2650  */
2651 static int
2652 hdd_update_reg_chan_info(struct hdd_adapter *adapter,
2653 			 uint32_t channel_count, uint32_t *freq_list)
2654 {
2655 	int i;
2656 	struct hdd_channel_info *icv;
2657 	struct ch_params ch_params = {0};
2658 	uint8_t bw_offset = 0, chan = 0;
2659 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2660 	struct sap_config *sap_config =
2661 				&adapter->deflink->session.ap.sap_config;
2662 	mac_handle_t mac_handle;
2663 	uint8_t sub_20_chan_width = 0;
2664 	QDF_STATUS status;
2665 
2666 	mac_handle = hdd_ctx->mac_handle;
2667 	sap_config->channel_info_count = channel_count;
2668 
2669 	status = ucfg_mlme_get_sub_20_chan_width(hdd_ctx->psoc,
2670 						 &sub_20_chan_width);
2671 	if (QDF_IS_STATUS_ERROR(status))
2672 		hdd_err("Failed to get sub_20_chan_width config");
2673 
2674 	for (i = 0; i < channel_count; i++) {
2675 		icv = &sap_config->channel_info[i];
2676 		chan = wlan_reg_freq_to_chan(hdd_ctx->pdev,
2677 					     freq_list[i]);
2678 		if (chan == 0)
2679 			continue;
2680 
2681 		icv->freq = freq_list[i];
2682 		icv->ieee_chan_number = chan;
2683 		icv->max_reg_power = wlan_reg_get_channel_reg_power_for_freq(
2684 				hdd_ctx->pdev, freq_list[i]);
2685 
2686 		/* filling demo values */
2687 		icv->max_radio_power = HDD_MAX_TX_POWER;
2688 		icv->min_radio_power = HDD_MIN_TX_POWER;
2689 		/* not supported in current driver */
2690 		icv->max_antenna_gain = 0;
2691 
2692 		bw_offset = hdd_get_bw_offset(sap_config->acs_cfg.ch_width);
2693 		icv->reg_class_id =
2694 			wlan_hdd_find_opclass(mac_handle, chan, bw_offset);
2695 
2696 		if (WLAN_REG_IS_5GHZ_CH_FREQ(freq_list[i])) {
2697 			if (sap_phymode_is_eht(sap_config->SapHw_mode))
2698 				wlan_reg_set_create_punc_bitmap(&ch_params,
2699 								true);
2700 			ch_params.ch_width = sap_config->acs_cfg.ch_width;
2701 			wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
2702 								icv->freq,
2703 								0, &ch_params,
2704 								REG_CURRENT_PWR_MODE);
2705 			icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
2706 			icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
2707 		}
2708 
2709 		icv->flags = 0;
2710 		icv->flags = cds_get_vendor_reg_flags(hdd_ctx->pdev,
2711 				icv->freq,
2712 				sap_config->acs_cfg.ch_width,
2713 				sap_config->acs_cfg.is_ht_enabled,
2714 				sap_config->acs_cfg.is_vht_enabled,
2715 				sub_20_chan_width);
2716 		if (icv->flags & IEEE80211_CHAN_PASSIVE)
2717 			icv->flagext |= IEEE80211_CHAN_DFS;
2718 
2719 		hdd_debug("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
2720 			icv->freq, icv->flags,
2721 			icv->flagext, icv->ieee_chan_number,
2722 			icv->max_reg_power, icv->max_radio_power,
2723 			icv->min_radio_power, icv->reg_class_id,
2724 			icv->max_antenna_gain, icv->vht_center_freq_seg0,
2725 			icv->vht_center_freq_seg1);
2726 	}
2727 	return 0;
2728 }
2729 
2730 /* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
2731 #define CHAN_INFO_ATTR_FLAGS \
2732 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
2733 #define CHAN_INFO_ATTR_FLAG_EXT \
2734 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
2735 #define CHAN_INFO_ATTR_FREQ \
2736 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
2737 #define CHAN_INFO_ATTR_MAX_REG_POWER \
2738 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
2739 #define CHAN_INFO_ATTR_MAX_POWER \
2740 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
2741 #define CHAN_INFO_ATTR_MIN_POWER \
2742 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
2743 #define CHAN_INFO_ATTR_REG_CLASS_ID \
2744 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
2745 #define CHAN_INFO_ATTR_ANTENNA_GAIN \
2746 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
2747 #define CHAN_INFO_ATTR_VHT_SEG_0 \
2748 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
2749 #define CHAN_INFO_ATTR_VHT_SEG_1 \
2750 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
2751 
2752 #define CHAN_INFO_ATTR_FREQ_VHT_SEG_0 \
2753 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2754 #define CHAN_INFO_ATTR_FREQ_VHT_SEG_1 \
2755 	QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2756 
2757 /**
2758  * hdd_cfg80211_update_channel_info() - add channel info attributes
2759  * @hdd_ctx: pointer to hdd context
2760  * @skb: pointer to sk buff
2761  * @sap_config: pointer to SAP configuration
2762  * @idx: attribute index
2763  *
2764  * Return: Success(0) or reason code for failure
2765  */
2766 static int32_t
2767 hdd_cfg80211_update_channel_info(struct hdd_context *hdd_ctx,
2768 				 struct sk_buff *skb,
2769 				 struct sap_config *sap_config, int idx)
2770 {
2771 	struct nlattr *nla_attr, *channel;
2772 	struct hdd_channel_info *icv;
2773 	int i;
2774 	uint32_t freq_seg_0 = 0, freq_seg_1 = 0;
2775 	enum reg_wifi_band band;
2776 	uint8_t band_mask;
2777 
2778 	nla_attr = nla_nest_start(skb, idx);
2779 	if (!nla_attr)
2780 		goto fail;
2781 
2782 	for (i = 0; i < sap_config->channel_info_count; i++) {
2783 		channel = nla_nest_start(skb, i);
2784 		if (!channel)
2785 			goto fail;
2786 
2787 		icv = &sap_config->channel_info[i];
2788 		if (!icv) {
2789 			hdd_err("channel info not found");
2790 			goto fail;
2791 		}
2792 
2793 		band = wlan_reg_freq_to_band(icv->freq);
2794 		band_mask = 1 << band;
2795 
2796 		if (icv->vht_center_freq_seg0)
2797 			freq_seg_0 = wlan_reg_chan_band_to_freq(hdd_ctx->pdev,
2798 						    icv->vht_center_freq_seg0,
2799 						    band_mask);
2800 		if (icv->vht_center_freq_seg1)
2801 			freq_seg_1 = wlan_reg_chan_band_to_freq(hdd_ctx->pdev,
2802 						    icv->vht_center_freq_seg1,
2803 						    band_mask);
2804 
2805 		if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
2806 				icv->freq) ||
2807 		    nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
2808 				icv->flags) ||
2809 		    nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
2810 				icv->flagext) ||
2811 		    nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
2812 				icv->max_reg_power) ||
2813 		    nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
2814 				icv->max_radio_power) ||
2815 		    nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
2816 				icv->min_radio_power) ||
2817 		    nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
2818 				icv->reg_class_id) ||
2819 		    nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
2820 				icv->max_antenna_gain) ||
2821 		    nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
2822 				icv->vht_center_freq_seg0) ||
2823 		    nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
2824 				icv->vht_center_freq_seg1) ||
2825 		    nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_0,
2826 				freq_seg_0) ||
2827 		    nla_put_u32(skb, CHAN_INFO_ATTR_FREQ_VHT_SEG_1,
2828 				freq_seg_1)) {
2829 			hdd_err("put fail");
2830 			goto fail;
2831 		}
2832 		nla_nest_end(skb, channel);
2833 	}
2834 	nla_nest_end(skb, nla_attr);
2835 	return 0;
2836 fail:
2837 	hdd_err("nl channel update failed");
2838 	return -EINVAL;
2839 }
2840 #undef CHAN_INFO_ATTR_FLAGS
2841 #undef CHAN_INFO_ATTR_FLAG_EXT
2842 #undef CHAN_INFO_ATTR_FREQ
2843 #undef CHAN_INFO_ATTR_MAX_REG_POWER
2844 #undef CHAN_INFO_ATTR_MAX_POWER
2845 #undef CHAN_INFO_ATTR_MIN_POWER
2846 #undef CHAN_INFO_ATTR_REG_CLASS_ID
2847 #undef CHAN_INFO_ATTR_ANTENNA_GAIN
2848 #undef CHAN_INFO_ATTR_VHT_SEG_0
2849 #undef CHAN_INFO_ATTR_VHT_SEG_1
2850 
2851 #undef CHAN_INFO_ATTR_FREQ_VHT_SEG_0
2852 #undef CHAN_INFO_ATTR_FREQ_VHT_SEG_1
2853 
2854 /**
2855  * hdd_cfg80211_update_pcl() - add pcl info attributes
2856  * @hdd_ctx: pointer to hdd context
2857  * @skb: pointer to sk buff
2858  * @ch_list_count: number of channels to add
2859  * @idx: attribute index
2860  * @vendor_pcl_list: PCL list
2861  * @vendor_weight_list: PCL weights
2862  *
2863  * Return: Success(0) or reason code for failure
2864  */
2865 static int32_t
2866 hdd_cfg80211_update_pcl(struct hdd_context *hdd_ctx,
2867 			struct sk_buff *skb,
2868 			uint8_t ch_list_count, int idx,
2869 			uint32_t *vendor_pcl_list, uint8_t *vendor_weight_list)
2870 {
2871 	struct nlattr *nla_attr, *channel;
2872 	int i;
2873 	uint8_t chan;
2874 
2875 	nla_attr = nla_nest_start(skb, idx);
2876 	if (!nla_attr)
2877 		goto fail;
2878 
2879 	for (i = 0; i < ch_list_count; i++) {
2880 		channel = nla_nest_start(skb, i);
2881 		if (!channel)
2882 			goto fail;
2883 
2884 		chan = (uint8_t)wlan_reg_freq_to_chan(hdd_ctx->pdev,
2885 						      vendor_pcl_list[i]);
2886 
2887 		if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL, chan) ||
2888 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
2889 				vendor_pcl_list[i]) ||
2890 		    nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
2891 			       vendor_weight_list[i])) {
2892 			hdd_err("put fail");
2893 			goto fail;
2894 		}
2895 		nla_nest_end(skb, channel);
2896 	}
2897 	nla_nest_end(skb, nla_attr);
2898 
2899 	return 0;
2900 fail:
2901 	hdd_err("updating pcl list failed");
2902 	return -EINVAL;
2903 }
2904 
2905 static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
2906 			      struct sap_config *sap_config,
2907 			      enum band_info *band)
2908 {
2909 	/* Get scan band */
2910 	if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2911 	   (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
2912 		*band = BAND_2G;
2913 	} else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
2914 		*band = BAND_5G;
2915 	} else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
2916 		*band = BAND_ALL;
2917 	}
2918 }
2919 
2920 /**
2921  * wlan_hdd_sap_get_valid_channellist() - Get SAPs valid channel list
2922  * @adapter: adapter
2923  * @channel_count: valid channel count
2924  * @freq_list: valid channel frequency (MHz) list
2925  * @band: frequency band
2926  *
2927  * This API returns valid channel list for SAP after removing nol and
2928  * channel which lies outside of configuration.
2929  *
2930  * Return: Zero on success, non-zero on failure
2931  */
2932 static int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
2933 					      uint32_t *channel_count,
2934 					      uint32_t *freq_list,
2935 					      enum band_info band)
2936 {
2937 	struct sap_config *sap_config;
2938 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2939 	uint32_t pcl_freqs[NUM_CHANNELS] = {0};
2940 	uint32_t chan_count;
2941 	uint32_t i;
2942 	QDF_STATUS status;
2943 	struct wlan_objmgr_pdev *pdev = hdd_ctx->pdev;
2944 
2945 	sap_config = &adapter->deflink->session.ap.sap_config;
2946 
2947 	status = policy_mgr_get_valid_chans(hdd_ctx->psoc,
2948 					    pcl_freqs,
2949 					    &chan_count);
2950 	if (QDF_IS_STATUS_ERROR(status)) {
2951 		hdd_err("Failed to get channel list");
2952 		return -EINVAL;
2953 	}
2954 
2955 	*channel_count = 0;
2956 	for (i = 0; i < chan_count; i++) {
2957 		if (*channel_count >= NUM_CHANNELS)
2958 			break;
2959 
2960 		if (band == BAND_2G &&
2961 		    WLAN_REG_IS_24GHZ_CH_FREQ(pcl_freqs[i]) &&
2962 		    !wlan_reg_is_disable_for_pwrmode(pdev, pcl_freqs[i],
2963 						     REG_CURRENT_PWR_MODE)) {
2964 			freq_list[*channel_count] = pcl_freqs[i];
2965 			*channel_count += 1;
2966 		} else if (band == BAND_5G &&
2967 			   (WLAN_REG_IS_5GHZ_CH_FREQ(pcl_freqs[i]) ||
2968 			    WLAN_REG_IS_6GHZ_CHAN_FREQ(pcl_freqs[i])) &&
2969 			   !wlan_reg_is_disable_for_pwrmode(
2970 							pdev, pcl_freqs[i],
2971 							REG_CURRENT_PWR_MODE)) {
2972 			freq_list[*channel_count] = pcl_freqs[i];
2973 			*channel_count += 1;
2974 		}
2975 	}
2976 
2977 	if (*channel_count == 0) {
2978 		hdd_err("no valid channel found");
2979 		return -EINVAL;
2980 	}
2981 
2982 	return 0;
2983 }
2984 
2985 /**
2986  * hdd_get_external_acs_event_len() - Get event buffer length for external ACS
2987  * @channel_count: number of channels for ACS operation
2988  *
2989  * Return: External ACS event (SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG) buffer length.
2990  */
2991 static int hdd_get_external_acs_event_len(uint32_t channel_count)
2992 {
2993 	uint32_t len = NLMSG_HDRLEN;
2994 	uint32_t i;
2995 
2996 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON */
2997 	len += nla_total_size(sizeof(u8));
2998 
2999 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED */
3000 	len += nla_total_size(sizeof(u32));
3001 
3002 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT */
3003 	len += nla_total_size(sizeof(u32));
3004 
3005 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH */
3006 	len += nla_total_size(sizeof(u8));
3007 
3008 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND */
3009 	len += nla_total_size(sizeof(u8));
3010 
3011 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE */
3012 	len += nla_total_size(sizeof(u32));
3013 
3014 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST */
3015 	len += nla_total_size(channel_count * sizeof(u32));
3016 
3017 	for (i = 0; i < channel_count; i++) {
3018 		/* QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL */
3019 		len += nla_total_size(sizeof(u8));
3020 
3021 		/* QCA_WLAN_VENDOR_ATTR_PCL_FREQ */
3022 		len += nla_total_size(sizeof(u32));
3023 
3024 		/* QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT */
3025 		len += nla_total_size(sizeof(u8));
3026 	}
3027 
3028 	for (i = 0; i < channel_count; i++) {
3029 		/* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ */
3030 		len += nla_total_size(sizeof(u16));
3031 
3032 		/* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS */
3033 		len += nla_total_size(sizeof(u32));
3034 
3035 		/* QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT */
3036 		len += nla_total_size(sizeof(u32));
3037 
3038 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER */
3039 		len += nla_total_size(sizeof(u8));
3040 
3041 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER */
3042 		len += nla_total_size(sizeof(u8));
3043 
3044 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER */
3045 		len += nla_total_size(sizeof(u8));
3046 
3047 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID */
3048 		len += nla_total_size(sizeof(u8));
3049 
3050 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN */
3051 		len += nla_total_size(sizeof(u8));
3052 
3053 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 */
3054 		len += nla_total_size(sizeof(u8));
3055 
3056 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 */
3057 		len += nla_total_size(sizeof(u8));
3058 
3059 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 */
3060 		len += nla_total_size(sizeof(u32));
3061 
3062 		/* VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 */
3063 		len += nla_total_size(sizeof(u32));
3064 	}
3065 
3066 	/* QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY */
3067 	len += nla_total_size(sizeof(u32));
3068 
3069 	return len;
3070 }
3071 
3072 int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
3073 				   uint8_t reason)
3074 {
3075 	struct sk_buff *skb = NULL;
3076 	struct sap_config *sap_config;
3077 	uint32_t channel_count = 0, status = -EINVAL;
3078 	uint32_t *freq_list;
3079 	uint32_t vendor_pcl_list[NUM_CHANNELS] = {0};
3080 	uint8_t vendor_weight_list[NUM_CHANNELS] = {0};
3081 	struct hdd_vendor_acs_chan_params acs_chan_params;
3082 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3083 	enum band_info band = BAND_2G;
3084 	eCsrPhyMode phy_mode;
3085 	enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
3086 	uint32_t i, id;
3087 	QDF_STATUS qdf_status;
3088 	bool is_external_acs_policy = cfg_default(CFG_EXTERNAL_ACS_POLICY);
3089 	uint32_t len;
3090 
3091 	if (!hdd_ctx) {
3092 		hdd_err("HDD context is NULL");
3093 		return -EINVAL;
3094 	}
3095 
3096 	hdd_enter();
3097 	sap_config = &adapter->deflink->session.ap.sap_config;
3098 	/* When first 2 connections are on the same frequency band,
3099 	 * then PCL would include only channels from the other
3100 	 * frequency band on which no connections are active
3101 	 */
3102 	if ((policy_mgr_get_connection_count(hdd_ctx->psoc) == 2) &&
3103 	    (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
3104 		struct policy_mgr_conc_connection_info	*conc_connection_info;
3105 
3106 		conc_connection_info = policy_mgr_get_conn_info(&i);
3107 		if (policy_mgr_are_2_freq_on_same_mac(hdd_ctx->psoc,
3108 			conc_connection_info[0].freq,
3109 			conc_connection_info[1].freq)) {
3110 			if (!WLAN_REG_IS_24GHZ_CH_FREQ(
3111 				sap_config->acs_cfg.pcl_chan_freq[0])) {
3112 				sap_config->acs_cfg.band =
3113 					QCA_ACS_MODE_IEEE80211A;
3114 				hdd_update_acs_channel_list(sap_config,
3115 					BAND_5G);
3116 			} else {
3117 				sap_config->acs_cfg.band =
3118 					QCA_ACS_MODE_IEEE80211G;
3119 				hdd_update_acs_channel_list(sap_config,
3120 					BAND_2G);
3121 			}
3122 		}
3123 	}
3124 
3125 	hdd_get_scan_band(hdd_ctx, &adapter->deflink->session.ap.sap_config,
3126 			  &band);
3127 
3128 	freq_list = qdf_mem_malloc(sizeof(uint32_t) * NUM_CHANNELS);
3129 	if (!freq_list)
3130 		return -ENOMEM;
3131 
3132 	if (sap_config->acs_cfg.freq_list) {
3133 		/* Copy INI or hostapd provided ACS channel range*/
3134 		for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
3135 			freq_list[i] = sap_config->acs_cfg.freq_list[i];
3136 		channel_count = sap_config->acs_cfg.ch_list_count;
3137 	} else {
3138 		/* No channel list provided, copy all valid channels */
3139 		wlan_hdd_sap_get_valid_channellist(adapter,
3140 			&channel_count,
3141 			freq_list,
3142 			band);
3143 	}
3144 
3145 	sap_config->channel_info = qdf_mem_malloc(
3146 					sizeof(struct hdd_channel_info) *
3147 					channel_count);
3148 	if (!sap_config->channel_info) {
3149 		status = -ENOMEM;
3150 		goto fail;
3151 	}
3152 
3153 	hdd_update_reg_chan_info(adapter, channel_count, freq_list);
3154 
3155 	/* Get phymode */
3156 	phy_mode = adapter->deflink->session.ap.sap_config.acs_cfg.hw_mode;
3157 
3158 	len = hdd_get_external_acs_event_len(channel_count);
3159 	id = QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG;
3160 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, &adapter->wdev,
3161 					       len, id, GFP_KERNEL);
3162 	if (!skb) {
3163 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
3164 		status = -ENOMEM;
3165 		goto fail;
3166 	}
3167 	/*
3168 	 * Application expects pcl to be a subset of channel list
3169 	 * Remove all channels which are not in channel list from pcl
3170 	 * and add weight as zero
3171 	 */
3172 	acs_chan_params.vendor_pcl_list = vendor_pcl_list;
3173 	acs_chan_params.vendor_weight_list = vendor_weight_list;
3174 
3175 	hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
3176 				   sap_config);
3177 
3178 	if (acs_chan_params.pcl_count) {
3179 		hdd_debug("ACS PCL list: len: %d",
3180 			  acs_chan_params.pcl_count);
3181 		for (i = 0; i < acs_chan_params.pcl_count; i++)
3182 			hdd_debug("channel_frequency: %u, weight: %u",
3183 				  acs_chan_params.
3184 				  vendor_pcl_list[i],
3185 				  acs_chan_params.
3186 				  vendor_weight_list[i]);
3187 	}
3188 
3189 	qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
3190 						       &is_external_acs_policy);
3191 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3192 		hdd_err("get_external_acs_policy failed, set default");
3193 
3194 	if (is_external_acs_policy) {
3195 		acs_policy =
3196 			QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
3197 	} else {
3198 		acs_policy =
3199 			QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
3200 	}
3201 	/* Update values in NL buffer */
3202 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
3203 		       reason) ||
3204 	    nla_put_flag(skb,
3205 		QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
3206 	    nla_put_flag(skb,
3207 		QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
3208 		||
3209 	    nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
3210 		       sap_config->acs_cfg.ch_width) ||
3211 	    nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
3212 		       band) ||
3213 	    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
3214 		       phy_mode) ||
3215 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
3216 		    channel_count * sizeof(uint32_t), freq_list)) {
3217 		hdd_err("nla put fail");
3218 		goto fail;
3219 	}
3220 	status =
3221 	hdd_cfg80211_update_pcl(hdd_ctx, skb,
3222 				acs_chan_params.pcl_count,
3223 				QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
3224 				vendor_pcl_list,
3225 				vendor_weight_list);
3226 
3227 	if (status != 0)
3228 		goto fail;
3229 
3230 	id = QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO;
3231 
3232 	status = hdd_cfg80211_update_channel_info(hdd_ctx, skb, sap_config, id);
3233 	if (status != 0)
3234 		goto fail;
3235 
3236 	status = nla_put_u32(skb,
3237 			     QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
3238 			     acs_policy);
3239 
3240 	if (status != 0)
3241 		goto fail;
3242 
3243 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
3244 	qdf_mem_free(freq_list);
3245 	qdf_mem_free(sap_config->channel_info);
3246 
3247 	return 0;
3248 fail:
3249 	qdf_mem_free(freq_list);
3250 	if (sap_config->channel_info)
3251 		qdf_mem_free(sap_config->channel_info);
3252 	wlan_cfg80211_vendor_free_skb(skb);
3253 	return status;
3254 }
3255 
3256 /**
3257  * hdd_create_acs_timer(): Initialize vendor ACS timer
3258  * @adapter: pointer to SAP adapter struct
3259  *
3260  * This function initializes the vendor ACS timer.
3261  *
3262  * Return: Status of create vendor ACS timer
3263  */
3264 static int hdd_create_acs_timer(struct hdd_adapter *adapter)
3265 {
3266 	struct hdd_external_acs_timer_context *timer_context;
3267 	QDF_STATUS status;
3268 
3269 	if (adapter->deflink->session.ap.vendor_acs_timer_initialized)
3270 		return 0;
3271 
3272 	hdd_debug("Starting vendor app based ACS");
3273 	timer_context = qdf_mem_malloc(sizeof(*timer_context));
3274 	if (!timer_context)
3275 		return -ENOMEM;
3276 
3277 	timer_context->adapter = adapter;
3278 
3279 	set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->deflink->link_flags);
3280 	status = qdf_mc_timer_init(
3281 		  &adapter->deflink->session.ap.vendor_acs_timer,
3282 		  QDF_TIMER_TYPE_SW,
3283 		  hdd_acs_response_timeout_handler, timer_context);
3284 	if (status != QDF_STATUS_SUCCESS) {
3285 		hdd_err("Failed to initialize acs response timeout timer");
3286 		return -EFAULT;
3287 	}
3288 	adapter->deflink->session.ap.vendor_acs_timer_initialized = true;
3289 	return 0;
3290 }
3291 
3292 static const struct nla_policy
3293 wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1] = {
3294 	[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
3295 	[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
3296 	[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
3297 	[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
3298 	[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
3299 	[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_BINARY,
3300 				.len = sizeof(NLA_U8) * NUM_CHANNELS },
3301 	[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_BINARY,
3302 				.len = sizeof(NLA_U32) * NUM_CHANNELS },
3303 	[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED] = { .type = NLA_FLAG },
3304 	[QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP] = { .type = NLA_U16 },
3305 	[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED] = { .type = NLA_FLAG },
3306 	[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL] = { .type = NLA_U8 },
3307 	[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME] = { .type = NLA_U32 },
3308 };
3309 
3310 int hdd_start_vendor_acs(struct hdd_adapter *adapter)
3311 {
3312 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3313 	int status;
3314 	QDF_STATUS qdf_status;
3315 	bool is_acs_support_for_dfs_ltecoex = cfg_default(CFG_USER_ACS_DFS_LTE);
3316 
3317 	status = hdd_create_acs_timer(adapter);
3318 	if (status != 0) {
3319 		hdd_err("failed to create acs timer");
3320 		return status;
3321 	}
3322 	status = hdd_update_acs_timer_reason(adapter,
3323 		QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
3324 	if (status != 0) {
3325 		hdd_err("failed to update acs timer reason");
3326 		return status;
3327 	}
3328 	qdf_status = ucfg_mlme_get_acs_support_for_dfs_ltecoex(
3329 				hdd_ctx->psoc,
3330 				&is_acs_support_for_dfs_ltecoex);
3331 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
3332 		hdd_err("get_acs_support_for_dfs_ltecoex failed, set def");
3333 
3334 	if (is_acs_support_for_dfs_ltecoex)
3335 		status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
3336 				WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
3337 				true));
3338 	else
3339 		status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
3340 				WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink),
3341 				false));
3342 
3343 	return status;
3344 }
3345 
3346 /**
3347  * hdd_avoid_acs_channels() - Avoid acs channels
3348  * @hdd_ctx: Pointer to the hdd context
3349  * @sap_config: Sap config structure pointer
3350  *
3351  * This function avoids channels from the acs corresponding to
3352  * the frequencies configured in the ini sap_avoid_acs_freq_list
3353  *
3354  * Return: None
3355  */
3356 
3357 #ifdef SAP_AVOID_ACS_FREQ_LIST
3358 static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
3359 				   struct sap_config *sap_config)
3360 {
3361 	int i, j, ch_cnt = 0;
3362 	uint16_t avoid_acs_freq_list[CFG_VALID_CHANNEL_LIST_LEN];
3363 	uint8_t avoid_acs_freq_list_num;
3364 
3365 	ucfg_mlme_get_acs_avoid_freq_list(hdd_ctx->psoc,
3366 					  avoid_acs_freq_list,
3367 					  &avoid_acs_freq_list_num);
3368 
3369 	for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
3370 		for (j = 0; j < avoid_acs_freq_list_num; j++) {
3371 			if (sap_config->acs_cfg.freq_list[i] ==
3372 						avoid_acs_freq_list[j]) {
3373 				hdd_debug("skip freq %d",
3374 					  sap_config->acs_cfg.freq_list[i]);
3375 				break;
3376 			}
3377 		}
3378 		if (j == avoid_acs_freq_list_num)
3379 			sap_config->acs_cfg.freq_list[ch_cnt++] =
3380 					sap_config->acs_cfg.freq_list[i];
3381 	}
3382 	sap_config->acs_cfg.ch_list_count = ch_cnt;
3383 }
3384 #else
3385 static void hdd_avoid_acs_channels(struct hdd_context *hdd_ctx,
3386 				   struct sap_config *sap_config)
3387 {
3388 }
3389 #endif
3390 
3391 void wlan_hdd_trim_acs_channel_list(uint32_t *pcl, uint8_t pcl_count,
3392 				    uint32_t *org_freq_list,
3393 				    uint8_t *org_ch_list_count)
3394 {
3395 	uint16_t i, j, ch_list_count = 0;
3396 
3397 	if (*org_ch_list_count >= NUM_CHANNELS) {
3398 		hdd_err("org_ch_list_count too big %d",
3399 			*org_ch_list_count);
3400 		return;
3401 	}
3402 
3403 	if (pcl_count >= NUM_CHANNELS) {
3404 		hdd_err("pcl_count is too big %d", pcl_count);
3405 		return;
3406 	}
3407 
3408 	hdd_debug("Update ACS chan freq with PCL");
3409 	for (j = 0; j < *org_ch_list_count; j++)
3410 		for (i = 0; i < pcl_count; i++)
3411 			if (pcl[i] == org_freq_list[j]) {
3412 				org_freq_list[ch_list_count++] = pcl[i];
3413 				break;
3414 			}
3415 
3416 	*org_ch_list_count = ch_list_count;
3417 }
3418 
3419 /* wlan_hdd_dump_freq_list() - Dump the ACS master frequency list
3420  *
3421  * @freq_list: Frequency list
3422  * @num_freq: num of frequencies in list
3423  *
3424  * Dump the ACS master frequency list.
3425  */
3426 static inline
3427 void wlan_hdd_dump_freq_list(uint32_t *freq_list, uint8_t num_freq)
3428 {
3429 	uint32_t buf_len = 0;
3430 	uint32_t i = 0, j = 0;
3431 	uint8_t *master_chlist;
3432 
3433 	if (num_freq >= NUM_CHANNELS)
3434 		return;
3435 
3436 	buf_len = NUM_CHANNELS * 4;
3437 	master_chlist = qdf_mem_malloc(buf_len);
3438 
3439 	if (!master_chlist)
3440 		return;
3441 
3442 	for (i = 0; i < num_freq && j < buf_len; i++) {
3443 		j += qdf_scnprintf(master_chlist + j, buf_len - j,
3444 				   "%d ", freq_list[i]);
3445 	}
3446 
3447 	hdd_debug("Master channel list: %s", master_chlist);
3448 	qdf_mem_free(master_chlist);
3449 }
3450 
3451 void wlan_hdd_handle_zero_acs_list(struct hdd_context *hdd_ctx,
3452 				   uint32_t *acs_freq_list,
3453 				   uint8_t *acs_ch_list_count,
3454 				   uint32_t *org_freq_list,
3455 				   uint8_t org_ch_list_count)
3456 {
3457 	uint16_t i, sta_count;
3458 	uint32_t acs_chan_default = 0, acs_dfs_chan = 0;
3459 	bool force_sap_allowed = false;
3460 	enum channel_state state;
3461 
3462 	if (!acs_ch_list_count || *acs_ch_list_count > 0 ||
3463 	    !acs_freq_list) {
3464 		return;
3465 	}
3466 	if (!org_ch_list_count || !org_freq_list)
3467 		return;
3468 
3469 	if (!policy_mgr_is_force_scc(hdd_ctx->psoc))
3470 		return;
3471 	sta_count = policy_mgr_mode_specific_connection_count
3472 			(hdd_ctx->psoc, PM_STA_MODE, NULL);
3473 	sta_count += policy_mgr_mode_specific_connection_count
3474 			(hdd_ctx->psoc, PM_P2P_CLIENT_MODE, NULL);
3475 
3476 	ucfg_mlme_get_force_sap_enabled(hdd_ctx->psoc, &force_sap_allowed);
3477 	if (!sta_count && !force_sap_allowed)
3478 		return;
3479 
3480 	wlan_hdd_dump_freq_list(org_freq_list, org_ch_list_count);
3481 
3482 	for (i = 0; i < org_ch_list_count; i++) {
3483 		state = wlan_reg_get_channel_state_for_pwrmode(
3484 				hdd_ctx->pdev, org_freq_list[i],
3485 				REG_CURRENT_PWR_MODE);
3486 		if (state == CHANNEL_STATE_DISABLE ||
3487 		    state == CHANNEL_STATE_INVALID)
3488 			continue;
3489 
3490 		if (wlan_reg_is_6ghz_chan_freq(org_freq_list[i]) &&
3491 		    !wlan_reg_is_6ghz_psc_chan_freq(org_freq_list[i]))
3492 			continue;
3493 
3494 		if (!policy_mgr_is_safe_channel(hdd_ctx->psoc,
3495 						org_freq_list[i]))
3496 			continue;
3497 		/* Make dfs channel as last choice */
3498 		if (state == CHANNEL_STATE_DFS ||
3499 		    state == CHANNEL_STATE_PASSIVE) {
3500 			acs_dfs_chan = org_freq_list[i];
3501 			continue;
3502 		}
3503 		acs_chan_default = org_freq_list[i];
3504 		break;
3505 	}
3506 	if (!acs_chan_default) {
3507 		if (acs_dfs_chan)
3508 			acs_chan_default = acs_dfs_chan;
3509 		else
3510 			acs_chan_default = org_freq_list[0];
3511 	}
3512 
3513 	acs_freq_list[0] = acs_chan_default;
3514 	*acs_ch_list_count = 1;
3515 	hdd_debug("restore acs chan list to single freq %d", acs_chan_default);
3516 }
3517 
3518 /**
3519  * wlan_hdd_handle_single_ch_in_acs_list() - Handle acs list with single channel
3520  * @link_info: Link info pointer in HDD adapter
3521  *
3522  * If only one acs channel is left after filter, driver will return the channel
3523  * to hostapd without ACS scan.
3524  *
3525  * Return: None
3526  */
3527 static void
3528 wlan_hdd_handle_single_ch_in_acs_list(struct wlan_hdd_link_info *link_info)
3529 {
3530 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
3531 	uint32_t channel_bonding_mode_2g;
3532 	struct sap_config *sap_config;
3533 
3534 	sap_config = &link_info->session.ap.sap_config;
3535 	ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
3536 					    &channel_bonding_mode_2g);
3537 	sap_config->acs_cfg.start_ch_freq =
3538 		sap_config->acs_cfg.freq_list[0];
3539 	sap_config->acs_cfg.end_ch_freq =
3540 		sap_config->acs_cfg.freq_list[0];
3541 	sap_config->acs_cfg.pri_ch_freq =
3542 			      sap_config->acs_cfg.freq_list[0];
3543 	if (sap_config->acs_cfg.pri_ch_freq <=
3544 	    WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484) &&
3545 	    sap_config->acs_cfg.ch_width >=
3546 				CH_WIDTH_40MHZ &&
3547 	    !channel_bonding_mode_2g) {
3548 		sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
3549 		hdd_debug("2.4ghz channel resetting BW to %d 2.4 cbmode %d",
3550 			  sap_config->acs_cfg.ch_width,
3551 			  channel_bonding_mode_2g);
3552 	}
3553 
3554 	wlan_sap_set_sap_ctx_acs_cfg(
3555 		WLAN_HDD_GET_SAP_CTX_PTR(link_info), sap_config);
3556 	sap_config_acs_result(hdd_ctx->mac_handle,
3557 			      WLAN_HDD_GET_SAP_CTX_PTR(link_info),
3558 			    sap_config->acs_cfg.ht_sec_ch_freq);
3559 	sap_config->ch_params.ch_width =
3560 			sap_config->acs_cfg.ch_width;
3561 	sap_config->ch_params.sec_ch_offset =
3562 			wlan_reg_freq_to_chan(
3563 			hdd_ctx->pdev,
3564 			sap_config->acs_cfg.ht_sec_ch_freq);
3565 	sap_config->ch_params.center_freq_seg0 =
3566 	wlan_reg_freq_to_chan(
3567 		hdd_ctx->pdev,
3568 		sap_config->acs_cfg.vht_seg0_center_ch_freq);
3569 	sap_config->ch_params.center_freq_seg1 =
3570 	wlan_reg_freq_to_chan(
3571 		hdd_ctx->pdev,
3572 		sap_config->acs_cfg.vht_seg1_center_ch_freq);
3573 	sap_config->ch_params.mhz_freq_seg0 =
3574 		sap_config->acs_cfg.vht_seg0_center_ch_freq;
3575 	sap_config->ch_params.mhz_freq_seg1 =
3576 		sap_config->acs_cfg.vht_seg1_center_ch_freq;
3577 	/*notify hostapd about channel override */
3578 	wlan_hdd_cfg80211_acs_ch_select_evt(link_info, true);
3579 	wlansap_dcs_set_wlan_interference_mitigation_on_band(
3580 		WLAN_HDD_GET_SAP_CTX_PTR(link_info),
3581 		sap_config);
3582 }
3583 
3584 #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC)
3585 static void wlan_hdd_set_sap_acs_ch_width_320(struct sap_config *sap_config)
3586 {
3587 	sap_config->acs_cfg.ch_width = CH_WIDTH_320MHZ;
3588 }
3589 
3590 static bool wlan_hdd_is_sap_acs_ch_width_320(struct sap_config *sap_config)
3591 {
3592 	return sap_config->acs_cfg.ch_width == CH_WIDTH_320MHZ;
3593 }
3594 
3595 static void wlan_hdd_set_chandef(struct wlan_objmgr_vdev *vdev,
3596 				 struct cfg80211_chan_def *chandef)
3597 {
3598 	if (vdev->vdev_mlme.des_chan->ch_width != CH_WIDTH_320MHZ)
3599 		return;
3600 
3601 	chandef->width = NL80211_CHAN_WIDTH_320;
3602 	/* Set center_freq1 to center frequency of complete 320MHz */
3603 	chandef->center_freq1 = vdev->vdev_mlme.des_chan->ch_cfreq2;
3604 }
3605 #else /* !WLAN_FEATURE_11BE */
3606 static inline
3607 void wlan_hdd_set_sap_acs_ch_width_320(struct sap_config *sap_config)
3608 {
3609 }
3610 
3611 static inline
3612 bool wlan_hdd_is_sap_acs_ch_width_320(struct sap_config *sap_config)
3613 {
3614 	return false;
3615 }
3616 
3617 static inline void wlan_hdd_set_chandef(struct wlan_objmgr_vdev *vdev,
3618 					struct cfg80211_chan_def *chandef)
3619 {
3620 }
3621 #endif /* WLAN_FEATURE_11BE */
3622 
3623 #ifdef WLAN_FEATURE_11BE
3624 /**
3625  * wlan_hdd_acs_set_eht_enabled() - set is_eht_enabled of acs config
3626  * @sap_config: pointer to sap_config
3627  * @eht_enabled: eht is enabled
3628  *
3629  * Return: void
3630  */
3631 static void wlan_hdd_acs_set_eht_enabled(struct sap_config *sap_config,
3632 					 bool eht_enabled)
3633 {
3634 	if (!sap_config) {
3635 		hdd_err("Invalid sap_config");
3636 		return;
3637 	}
3638 
3639 	sap_config->acs_cfg.is_eht_enabled = eht_enabled;
3640 }
3641 #else
3642 static void wlan_hdd_acs_set_eht_enabled(struct sap_config *sap_config,
3643 					 bool eht_enabled)
3644 {
3645 }
3646 #endif /* WLAN_FEATURE_11BE */
3647 
3648 static uint16_t wlan_hdd_update_bw_from_mlme(struct hdd_context *hdd_ctx,
3649 					     struct sap_config *sap_config)
3650 {
3651 	uint16_t ch_width, temp_ch_width = 0;
3652 	QDF_STATUS status;
3653 	uint8_t hw_mode = HW_MODE_DBS;
3654 	struct wma_caps_per_phy caps_per_phy = {0};
3655 
3656 	ch_width = sap_config->acs_cfg.ch_width;
3657 
3658 	if (ch_width > CH_WIDTH_80P80MHZ)
3659 		return ch_width;
3660 
3661 	/* 2.4ghz is already handled for acs */
3662 	if (sap_config->acs_cfg.end_ch_freq <=
3663 	    WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484))
3664 		return ch_width;
3665 
3666 	if (!policy_mgr_is_dbs_enable(hdd_ctx->psoc))
3667 		hw_mode = HW_MODE_DBS_NONE;
3668 
3669 	status = wma_get_caps_for_phyidx_hwmode(&caps_per_phy, hw_mode,
3670 						CDS_BAND_5GHZ);
3671 	if (!QDF_IS_STATUS_SUCCESS(status))
3672 		return ch_width;
3673 
3674 	switch (ch_width) {
3675 	case CH_WIDTH_80P80MHZ:
3676 		if (!(caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ))
3677 		{
3678 			if (caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_160MHZ)
3679 				temp_ch_width = CH_WIDTH_160MHZ;
3680 			else
3681 				temp_ch_width = CH_WIDTH_80MHZ;
3682 		}
3683 		break;
3684 	case CH_WIDTH_160MHZ:
3685 		if (!((caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_80P80_160MHZ)
3686 		      || (caps_per_phy.vht_5g & WMI_VHT_CAP_CH_WIDTH_160MHZ)))
3687 				temp_ch_width = CH_WIDTH_80MHZ;
3688 		break;
3689 	default:
3690 		break;
3691 	}
3692 
3693 	if (!temp_ch_width)
3694 		return ch_width;
3695 
3696 	hdd_debug("ch_width updated from %d to %d vht_5g: %x", ch_width,
3697 		  temp_ch_width, caps_per_phy.vht_5g);
3698 	return temp_ch_width;
3699 }
3700 
3701 /**
3702  *  wlan_hdd_check_is_acs_request_same() - API to compare ongoing ACS and
3703  *					current received ACS request
3704  * @adapter: hdd adapter
3705  * @data: ACS data
3706  * @data_len: ACS data length
3707  *
3708  * This function is used to compare ongoing ACS params with current received
3709  * ACS request on same interface.
3710  *
3711  * Return: true only if ACS request received is same as ongoing ACS
3712  */
3713 static bool wlan_hdd_check_is_acs_request_same(struct hdd_adapter *adapter,
3714 					       const void *data, int data_len)
3715 {
3716 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
3717 	uint8_t hw_mode, ht_enabled, ht40_enabled, vht_enabled, eht_enabled;
3718 	struct sap_config *sap_config;
3719 	uint32_t last_scan_ageout_time = 0;
3720 	uint8_t ch_list_count;
3721 	uint16_t ch_width;
3722 	int ret, i, j;
3723 	struct wlan_objmgr_psoc *psoc;
3724 
3725 	ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
3726 				      data_len,
3727 				      wlan_hdd_cfg80211_do_acs_policy);
3728 	if (ret) {
3729 		hdd_err("Invalid ATTR");
3730 		return false;
3731 	}
3732 
3733 	if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE])
3734 		return false;
3735 
3736 	sap_config = &adapter->deflink->session.ap.sap_config;
3737 
3738 	hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
3739 	if (sap_config->acs_cfg.master_acs_cfg.hw_mode != hw_mode)
3740 		return false;
3741 
3742 	ht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
3743 	if (sap_config->acs_cfg.master_acs_cfg.ht != ht_enabled)
3744 		return false;
3745 
3746 	ht40_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
3747 	if (sap_config->acs_cfg.master_acs_cfg.ht40 != ht40_enabled)
3748 		return false;
3749 
3750 	vht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
3751 	if (sap_config->acs_cfg.master_acs_cfg.vht != vht_enabled)
3752 		return false;
3753 
3754 	eht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED]);
3755 	if (sap_config->acs_cfg.master_acs_cfg.eht != eht_enabled)
3756 		return false;
3757 
3758 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH])
3759 		ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
3760 	else
3761 		ch_width = 0;
3762 	if (sap_config->acs_cfg.master_acs_cfg.ch_width != ch_width)
3763 		return false;
3764 
3765 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME]) {
3766 		last_scan_ageout_time =
3767 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME]);
3768 	} else {
3769 		psoc = wlan_vdev_get_psoc(adapter->deflink->vdev);
3770 		if (psoc)
3771 			wlan_scan_get_last_scan_ageout_time(
3772 							psoc,
3773 							&last_scan_ageout_time);
3774 	}
3775 	if (sap_config->acs_cfg.last_scan_ageout_time != last_scan_ageout_time)
3776 		return false;
3777 
3778 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
3779 		uint32_t *freq =
3780 			nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
3781 
3782 		ch_list_count = nla_len(
3783 				tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
3784 				sizeof(uint32_t);
3785 		if (sap_config->acs_cfg.master_ch_list_count != ch_list_count)
3786 			return false;
3787 		for (i = 0; i < ch_list_count; i++) {
3788 			j = 0;
3789 			while (j < ch_list_count && freq[i] !=
3790 			       sap_config->acs_cfg.master_freq_list[j])
3791 				j++;
3792 			if (j == ch_list_count)
3793 				return false;
3794 		}
3795 	} else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
3796 		uint8_t *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3797 
3798 		ch_list_count = nla_len(
3799 					tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
3800 		if (sap_config->acs_cfg.master_ch_list_count != ch_list_count)
3801 			return false;
3802 		for (i = 0; i < ch_list_count; i++) {
3803 			j = 0;
3804 			while (j < ch_list_count &&
3805 			       wlan_reg_legacy_chan_to_freq(
3806 			       adapter->hdd_ctx->pdev, tmp[i]) !=
3807 			       sap_config->acs_cfg.master_freq_list[j])
3808 				j++;
3809 			if (j == ch_list_count)
3810 				return false;
3811 		}
3812 	}
3813 
3814 	return true;
3815 }
3816 
3817 #ifndef WLAN_FEATURE_LL_LT_SAP
3818 /**
3819  * hdd_remove_passive_dfs_acs_channel_for_ll_sap(): Remove passive/dfs channel
3820  * for LL SAP
3821  * @sap_config: Pointer to sap_config
3822  * @psoc: Pointer to psoc
3823  * @pdev: Pointer to pdev
3824  * @vdev_id: Vdev Id
3825  *
3826  * This function will remove passive/dfs acs channel for low latency SAP
3827  * which are configured through userspace.
3828  *
3829  * Return: void
3830  */
3831 static void hdd_remove_passive_dfs_acs_channel_for_ll_sap(
3832 					struct sap_config *sap_config,
3833 					struct wlan_objmgr_psoc *psoc,
3834 					struct wlan_objmgr_pdev *pdev,
3835 					uint8_t vdev_id)
3836 {
3837 	uint32_t i, ch_cnt = 0;
3838 	uint32_t freq = 0;
3839 
3840 	if (!policy_mgr_is_vdev_ll_sap(psoc, vdev_id))
3841 		return;
3842 
3843 	for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
3844 		freq = sap_config->acs_cfg.freq_list[i];
3845 
3846 		/* Remove passive/dfs channel for LL SAP */
3847 		if (wlan_reg_is_passive_for_freq(pdev, freq) ||
3848 		    wlan_reg_is_dfs_for_freq(pdev, freq))
3849 			continue;
3850 
3851 		sap_config->acs_cfg.freq_list[ch_cnt++] = freq;
3852 	}
3853 
3854 	if (ch_cnt != sap_config->acs_cfg.ch_list_count) {
3855 		hdd_debug("New count after modification %d", ch_cnt);
3856 		sap_config->acs_cfg.ch_list_count = ch_cnt;
3857 		sap_dump_acs_channel(&sap_config->acs_cfg);
3858 	}
3859 }
3860 #else
3861 static inline void
3862 hdd_remove_passive_dfs_acs_channel_for_ll_sap(struct sap_config *sap_config,
3863 					      struct wlan_objmgr_psoc *psoc,
3864 					      struct wlan_objmgr_pdev *pdev,
3865 					      uint8_t vdev_id)
3866 {
3867 }
3868 #endif
3869 
3870 /* Stored ACS Frequency timeout in msec */
3871 #define STORED_ACS_FREQ_TIMEOUT 5000
3872 static bool
3873 wlan_hdd_is_prev_acs_freq_present_in_acs_config(struct sap_config *sap_cfg)
3874 {
3875 	uint32_t i = 0;
3876 	bool prev_acs_freq_found = false;
3877 
3878 	if (!qdf_system_time_before(
3879 		qdf_get_time_of_the_day_ms(),
3880 		sap_cfg->last_acs_complete_time + STORED_ACS_FREQ_TIMEOUT))
3881 		return prev_acs_freq_found;
3882 
3883 	for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
3884 		if (sap_cfg->acs_cfg.freq_list[i] == sap_cfg->last_acs_freq) {
3885 			prev_acs_freq_found = true;
3886 			break;
3887 		}
3888 	}
3889 
3890 	return prev_acs_freq_found;
3891 }
3892 
3893 static bool
3894 wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(struct hdd_adapter *adapter)
3895 {
3896 	struct hdd_context *hdd_ctx;
3897 	struct sap_config *sap_config;
3898 	int status;
3899 	bool prev_acs_freq_valid = false;
3900 	struct sap_context *sap_ctx;
3901 
3902 	if (!adapter) {
3903 		hdd_err("adapter is NULL");
3904 		return prev_acs_freq_valid;
3905 	}
3906 
3907 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
3908 	status = wlan_hdd_validate_context(hdd_ctx);
3909 	if (0 != status) {
3910 		hdd_err("Invalid HDD context");
3911 		return prev_acs_freq_valid;
3912 	}
3913 
3914 	sap_config = &adapter->deflink->session.ap.sap_config;
3915 	if (!sap_config) {
3916 		hdd_err("SAP config is NULL");
3917 		return prev_acs_freq_valid;
3918 	}
3919 
3920 	if (!sap_config->last_acs_freq || !sap_config->last_acs_complete_time)
3921 		return prev_acs_freq_valid;
3922 
3923 	if (!policy_mgr_is_vdev_ll_lt_sap(
3924 				hdd_ctx->psoc,
3925 				adapter->deflink->vdev_id))
3926 		return prev_acs_freq_valid;
3927 
3928 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink);
3929 	if (wlan_hdd_is_prev_acs_freq_present_in_acs_config(sap_config)) {
3930 		wlansap_update_ll_lt_sap_acs_result(sap_ctx,
3931 						    sap_config->last_acs_freq);
3932 
3933 		hdd_debug("vdev %d, return prev ACS freq %d stored at %lu, current time %lu",
3934 			  adapter->deflink->vdev_id, sap_config->last_acs_freq,
3935 			  sap_config->last_acs_complete_time,
3936 			  qdf_get_time_of_the_day_ms());
3937 
3938 		/* Notify to hostapd without storing the last acs frequency.
3939 		 * Reason for not storing the last acs frequency is to avoid
3940 		 * storing the same freq again and again
3941 		 */
3942 		wlan_hdd_cfg80211_acs_ch_select_evt(adapter->deflink, false);
3943 		wlansap_dcs_set_wlan_interference_mitigation_on_band(sap_ctx,
3944 								    sap_config);
3945 
3946 		prev_acs_freq_valid = true;
3947 	}
3948 
3949 	return prev_acs_freq_valid;
3950 }
3951 
3952 /**
3953  * hdd_remove_6ghz_freq_from_acs_list(): Removed 6 GHz frequecies from ACS list
3954  * @org_freq_list: ACS frequecny list
3955  * @org_ch_list_count: Number of frequencies in ACS list
3956  *
3957  * Return: None
3958  */
3959 static void hdd_remove_6ghz_freq_from_acs_list(uint32_t *org_freq_list,
3960 					       uint8_t *org_ch_list_count)
3961 {
3962 	uint16_t i, ch_list_count = 0;
3963 
3964 	hdd_debug("Remove 6 GHz channels from ACS list");
3965 	for (i = 0; i < *org_ch_list_count; i++) {
3966 		if (wlan_reg_is_6ghz_chan_freq(org_freq_list[i]))
3967 			continue;
3968 		org_freq_list[ch_list_count++] = org_freq_list[i];
3969 	}
3970 	*org_ch_list_count = ch_list_count;
3971 }
3972 
3973 /**
3974  * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
3975  * @wiphy:  Linux wiphy struct pointer
3976  * @wdev:   Linux wireless device struct pointer
3977  * @data:   ACS information from hostapd
3978  * @data_len: ACS information length
3979  *
3980  * This function handle DO_ACS Vendor command from hostapd, parses ACS config
3981  * and starts ACS procedure.
3982  *
3983  * Return: ACS procedure start status
3984  */
3985 static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
3986 					struct wireless_dev *wdev,
3987 					const void *data, int data_len)
3988 {
3989 	struct net_device *ndev = wdev->netdev;
3990 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
3991 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
3992 	struct sap_config *sap_config;
3993 	struct sap_context *sap_ctx;
3994 	struct hdd_ap_ctx *ap_ctx;
3995 	struct sk_buff *temp_skbuff;
3996 	int ret, i;
3997 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
3998 	bool ht_enabled, ht40_enabled, vht_enabled, eht_enabled;
3999 	uint16_t ch_width;
4000 	enum qca_wlan_vendor_acs_hw_mode hw_mode;
4001 	enum policy_mgr_con_mode pm_mode;
4002 	QDF_STATUS qdf_status;
4003 	bool is_vendor_acs_support = false;
4004 	bool is_external_acs_policy = false;
4005 	bool is_vendor_unsafe_ch_present = false;
4006 	bool sap_force_11n_for_11ac = 0;
4007 	bool go_force_11n_for_11ac = 0;
4008 	bool is_ll_lt_sap = false;
4009 	bool sap_force_11n = false;
4010 	bool go_11ac_override = 0;
4011 	bool sap_11ac_override = 0;
4012 	uint8_t vht_ch_width;
4013 	uint32_t channel_bonding_mode_2g;
4014 	uint32_t last_scan_ageout_time;
4015 	struct wlan_hdd_link_info *link_info = adapter->deflink;
4016 
4017 	/* ***Note*** Donot set SME config related to ACS operation here because
4018 	 * ACS operation is not synchronouse and ACS for Second AP may come when
4019 	 * ACS operation for first AP is going on. So only do_acs is split to
4020 	 * separate start_acs routine. Also SME-PMAC struct that is used to
4021 	 * pass parameters from HDD to SAP is global. Thus All ACS related SME
4022 	 * config shall be set only from start_acs.
4023 	 */
4024 
4025 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4026 		hdd_err("Command not allowed in FTM mode");
4027 		return -EPERM;
4028 	}
4029 
4030 	ret = wlan_hdd_validate_context(hdd_ctx);
4031 	if (ret)
4032 		return ret;
4033 
4034 	ucfg_mlme_get_sap_force_11n_for_11ac(hdd_ctx->psoc,
4035 					     &sap_force_11n_for_11ac);
4036 	ucfg_mlme_get_go_force_11n_for_11ac(hdd_ctx->psoc,
4037 					    &go_force_11n_for_11ac);
4038 	ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
4039 					    &channel_bonding_mode_2g);
4040 
4041 	if (policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc, link_info->vdev_id)) {
4042 		is_ll_lt_sap = true;
4043 		policy_mgr_ll_lt_sap_restart_concurrent_sap(hdd_ctx->psoc,
4044 							    true);
4045 	}
4046 
4047 	if (is_ll_lt_sap || sap_force_11n_for_11ac)
4048 		sap_force_11n = true;
4049 
4050 	if (!((adapter->device_mode == QDF_SAP_MODE) ||
4051 	      (adapter->device_mode == QDF_P2P_GO_MODE))) {
4052 		hdd_err("Invalid device mode %d", adapter->device_mode);
4053 		return -EINVAL;
4054 	}
4055 
4056 	if (cds_is_sub_20_mhz_enabled()) {
4057 		hdd_err("ACS not supported in sub 20 MHz ch wd.");
4058 		return -EINVAL;
4059 	}
4060 
4061 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
4062 
4063 	if (qdf_atomic_read(&ap_ctx->acs_in_progress) > 0) {
4064 		if (wlan_hdd_check_is_acs_request_same(adapter,
4065 						       data, data_len)) {
4066 			hdd_debug("Same ACS req as ongoing is received, return success");
4067 			ret = 0;
4068 			goto out;
4069 		}
4070 		hdd_err("ACS rejected as previous ACS req already in progress");
4071 		return -EINVAL;
4072 	} else {
4073 		qdf_atomic_set(&ap_ctx->acs_in_progress, 1);
4074 		qdf_event_reset(&link_info->acs_complete_event);
4075 	}
4076 
4077 	hdd_reg_wait_for_country_change(hdd_ctx);
4078 
4079 	ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
4080 					 data_len,
4081 					 wlan_hdd_cfg80211_do_acs_policy);
4082 	if (ret) {
4083 		hdd_err("Invalid ATTR");
4084 		goto out;
4085 	}
4086 
4087 	if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
4088 		hdd_err("Attr hw_mode failed");
4089 		ret = -EINVAL;
4090 		goto out;
4091 	}
4092 
4093 	sap_config = &ap_ctx->sap_config;
4094 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
4095 
4096 	/* Check and free if memory is already allocated for acs channel list */
4097 	wlan_hdd_undo_acs(link_info);
4098 
4099 	qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
4100 
4101 	hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
4102 	hdd_nofl_info("ACS request vid %d hw mode %d",
4103 		      link_info->vdev_id, hw_mode);
4104 	ht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
4105 	ht40_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
4106 	vht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
4107 	eht_enabled = nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED]);
4108 
4109 	sap_config->acs_cfg.master_acs_cfg.hw_mode = hw_mode;
4110 	sap_config->acs_cfg.master_acs_cfg.ht = ht_enabled;
4111 	sap_config->acs_cfg.master_acs_cfg.ht40 = ht40_enabled;
4112 	sap_config->acs_cfg.master_acs_cfg.vht = vht_enabled;
4113 	sap_config->acs_cfg.master_acs_cfg.eht = eht_enabled;
4114 
4115 	if (((adapter->device_mode == QDF_SAP_MODE) &&
4116 	      sap_force_11n) ||
4117 	    ((adapter->device_mode == QDF_P2P_GO_MODE) &&
4118 	      go_force_11n_for_11ac)) {
4119 		vht_enabled = 0;
4120 		hdd_info("VHT is Disabled in ACS");
4121 	}
4122 
4123 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
4124 		ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
4125 		sap_config->acs_cfg.master_acs_cfg.ch_width = ch_width;
4126 	} else {
4127 		if (ht_enabled && ht40_enabled)
4128 			ch_width = 40;
4129 		else
4130 			ch_width = 20;
4131 		sap_config->acs_cfg.master_acs_cfg.ch_width = 0;
4132 	}
4133 
4134 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED])
4135 		eht_enabled =
4136 			nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED]);
4137 	else
4138 		eht_enabled = 0;
4139 
4140 	if (ch_width == 320 && !eht_enabled)
4141 		ch_width = 160;
4142 
4143 	/* this may be possible, when sap_force_11n_for_11ac or
4144 	 * go_force_11n_for_11ac is set
4145 	 */
4146 	if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
4147 		if (ht_enabled && ht40_enabled)
4148 			ch_width = 40;
4149 		else
4150 			ch_width = 20;
4151 	}
4152 	if (is_ll_lt_sap)
4153 		ch_width = 20;
4154 
4155 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME])
4156 		last_scan_ageout_time =
4157 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ACS_LAST_SCAN_AGEOUT_TIME]);
4158 	else
4159 		wlan_scan_get_last_scan_ageout_time(hdd_ctx->psoc,
4160 						    &last_scan_ageout_time);
4161 
4162 	if (ch_width == 320)
4163 		wlan_hdd_set_sap_acs_ch_width_320(sap_config);
4164 	else if (ch_width == 160)
4165 		sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
4166 	else if (ch_width == 80)
4167 		sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
4168 	else if (ch_width == 40)
4169 		sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
4170 	else
4171 		sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
4172 
4173 	/* Firstly try to get channel frequencies */
4174 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
4175 		uint32_t *freq =
4176 			nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
4177 		sap_config->acs_cfg.ch_list_count = nla_len(
4178 			tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
4179 				sizeof(uint32_t);
4180 		if (sap_config->acs_cfg.ch_list_count) {
4181 			sap_config->acs_cfg.freq_list = qdf_mem_malloc(
4182 				sap_config->acs_cfg.ch_list_count *
4183 				sizeof(uint32_t));
4184 			sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
4185 				sap_config->acs_cfg.ch_list_count *
4186 				sizeof(uint32_t));
4187 			if (!sap_config->acs_cfg.freq_list ||
4188 			    !sap_config->acs_cfg.master_freq_list) {
4189 				ret = -ENOMEM;
4190 				goto out;
4191 			}
4192 
4193 			for (i = 0; i < sap_config->acs_cfg.ch_list_count;
4194 			     i++) {
4195 				sap_config->acs_cfg.master_freq_list[i] =
4196 									freq[i];
4197 				sap_config->acs_cfg.freq_list[i] = freq[i];
4198 			}
4199 			sap_config->acs_cfg.master_ch_list_count =
4200 					sap_config->acs_cfg.ch_list_count;
4201 		}
4202 	} else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
4203 		uint8_t *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
4204 
4205 		sap_config->acs_cfg.ch_list_count = nla_len(
4206 					tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
4207 		if (sap_config->acs_cfg.ch_list_count) {
4208 			sap_config->acs_cfg.freq_list = qdf_mem_malloc(
4209 					sap_config->acs_cfg.ch_list_count *
4210 					sizeof(uint32_t));
4211 			sap_config->acs_cfg.master_freq_list = qdf_mem_malloc(
4212 					sap_config->acs_cfg.ch_list_count *
4213 					sizeof(uint32_t));
4214 			if (!sap_config->acs_cfg.freq_list ||
4215 			    !sap_config->acs_cfg.master_freq_list) {
4216 				ret = -ENOMEM;
4217 				goto out;
4218 			}
4219 
4220 			/* convert channel to frequency */
4221 			for (i = 0; i < sap_config->acs_cfg.ch_list_count;
4222 			     i++) {
4223 				sap_config->acs_cfg.freq_list[i] =
4224 					wlan_reg_legacy_chan_to_freq(
4225 								hdd_ctx->pdev,
4226 								tmp[i]);
4227 				sap_config->acs_cfg.master_freq_list[i] =
4228 					sap_config->acs_cfg.freq_list[i];
4229 			}
4230 			sap_config->acs_cfg.master_ch_list_count =
4231 					sap_config->acs_cfg.ch_list_count;
4232 		}
4233 	}
4234 
4235 	if (!sap_config->acs_cfg.ch_list_count) {
4236 		hdd_err("acs config chan count 0");
4237 		ret = -EINVAL;
4238 		goto out;
4239 	} else {
4240 		hdd_nofl_debug("Dump raw ACS chanlist - ");
4241 		sap_dump_acs_channel(&sap_config->acs_cfg);
4242 	}
4243 
4244 	hdd_handle_acs_2g_preferred_sap_conc(hdd_ctx->psoc, adapter,
4245 					     sap_config);
4246 	hdd_avoid_acs_channels(hdd_ctx, sap_config);
4247 
4248 	pm_mode =
4249 		policy_mgr_qdf_opmode_to_pm_con_mode(hdd_ctx->psoc,
4250 						     adapter->device_mode,
4251 						     adapter->deflink->vdev_id);
4252 
4253 	/* Remove passive/dfs acs channel for ll sap */
4254 	hdd_remove_passive_dfs_acs_channel_for_ll_sap(
4255 						sap_config, hdd_ctx->psoc,
4256 						hdd_ctx->pdev,
4257 						link_info->vdev_id);
4258 
4259 	/* consult policy manager to get PCL */
4260 	qdf_status = policy_mgr_get_pcl(hdd_ctx->psoc, pm_mode,
4261 					sap_config->acs_cfg.pcl_chan_freq,
4262 					&sap_config->acs_cfg.pcl_ch_count,
4263 					sap_config->acs_cfg.
4264 					pcl_channels_weight_list,
4265 					NUM_CHANNELS,
4266 					link_info->vdev_id);
4267 
4268 	policy_mgr_get_pcl_channel_for_ll_sap_concurrency(
4269 				hdd_ctx->psoc,
4270 				link_info->vdev_id,
4271 				sap_config->acs_cfg.pcl_chan_freq,
4272 				sap_config->acs_cfg.pcl_channels_weight_list,
4273 				&sap_config->acs_cfg.pcl_ch_count);
4274 
4275 	sap_config->acs_cfg.band = hw_mode;
4276 
4277 	qdf_status = ucfg_mlme_get_external_acs_policy(hdd_ctx->psoc,
4278 						       &is_external_acs_policy);
4279 	if (!QDF_IS_STATUS_SUCCESS(qdf_status))
4280 		hdd_err("get_external_acs_policy failed");
4281 
4282 	sap_config->acs_cfg.acs_mode = true;
4283 
4284 	if (wlan_reg_get_keep_6ghz_sta_cli_connection(hdd_ctx->pdev))
4285 		hdd_remove_6ghz_freq_from_acs_list(
4286 					sap_config->acs_cfg.freq_list,
4287 					&sap_config->acs_cfg.ch_list_count);
4288 
4289 	if ((is_external_acs_policy &&
4290 	    policy_mgr_is_force_scc(hdd_ctx->psoc) &&
4291 	    policy_mgr_get_connection_count(hdd_ctx->psoc)) || is_ll_lt_sap) {
4292 		if (adapter->device_mode == QDF_SAP_MODE)
4293 			is_vendor_unsafe_ch_present =
4294 				wlansap_filter_vendor_unsafe_ch_freq(sap_ctx,
4295 								     sap_config);
4296 		wlan_hdd_trim_acs_channel_list(
4297 					sap_config->acs_cfg.pcl_chan_freq,
4298 					sap_config->acs_cfg.pcl_ch_count,
4299 					sap_config->acs_cfg.freq_list,
4300 					&sap_config->acs_cfg.ch_list_count);
4301 		if (!sap_config->acs_cfg.ch_list_count &&
4302 		    sap_config->acs_cfg.master_ch_list_count &&
4303 		    !is_vendor_unsafe_ch_present &&
4304 		    !is_ll_lt_sap)
4305 			wlan_hdd_handle_zero_acs_list(
4306 				hdd_ctx,
4307 				sap_config->acs_cfg.freq_list,
4308 				&sap_config->acs_cfg.ch_list_count,
4309 				sap_config->acs_cfg.master_freq_list,
4310 				sap_config->acs_cfg.master_ch_list_count);
4311 		/* if it is only one channel, send ACS event to upper layer */
4312 		if (sap_config->acs_cfg.ch_list_count == 1) {
4313 			wlan_hdd_handle_single_ch_in_acs_list(link_info);
4314 			ret = 0;
4315 			goto out;
4316 		} else if (!sap_config->acs_cfg.ch_list_count) {
4317 			hdd_err("channel list count 0");
4318 			ret = -EINVAL;
4319 			goto out;
4320 		}
4321 	} else if (adapter->device_mode == QDF_SAP_MODE) {
4322 		wlansap_filter_vendor_unsafe_ch_freq(sap_ctx, sap_config);
4323 		if (sap_config->acs_cfg.ch_list_count == 1) {
4324 			wlan_hdd_handle_single_ch_in_acs_list(link_info);
4325 			ret = 0;
4326 			goto out;
4327 		} else if (!sap_config->acs_cfg.ch_list_count) {
4328 			hdd_err("channel count 0 after vendor unsafe filter");
4329 			ret = -EINVAL;
4330 			goto out;
4331 		}
4332 	}
4333 
4334 	ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
4335 					ht_enabled, vht_enabled);
4336 	if (ret) {
4337 		hdd_err("set acs channel range failed");
4338 		goto out;
4339 	}
4340 
4341 	ucfg_mlme_is_go_11ac_override(hdd_ctx->psoc, &go_11ac_override);
4342 	ucfg_mlme_is_sap_11ac_override(hdd_ctx->psoc, &sap_11ac_override);
4343 	/* ACS override for android */
4344 	if (ht_enabled &&
4345 	    sap_config->acs_cfg.end_ch_freq >=
4346 		WLAN_REG_CH_TO_FREQ(CHAN_ENUM_5180) &&
4347 	    ((adapter->device_mode == QDF_SAP_MODE &&
4348 	      !sap_force_11n &&
4349 	      sap_11ac_override) ||
4350 	      (adapter->device_mode == QDF_P2P_GO_MODE &&
4351 	      !go_force_11n_for_11ac &&
4352 	      go_11ac_override))) {
4353 		vht_enabled = 1;
4354 		sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
4355 		qdf_status =
4356 			ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
4357 							&vht_ch_width);
4358 		ch_width = vht_ch_width;
4359 		sap_config->acs_cfg.ch_width = ch_width;
4360 	}
4361 
4362 	/* Check 2.4ghz cbmode and update BW if only 2.4 channels are present */
4363 	if (sap_config->acs_cfg.end_ch_freq <=
4364 	    WLAN_REG_CH_TO_FREQ(CHAN_ENUM_2484) &&
4365 	    sap_config->acs_cfg.ch_width >= eHT_CHANNEL_WIDTH_40MHZ) {
4366 
4367 		sap_config->acs_cfg.ch_width = channel_bonding_mode_2g ?
4368 			eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ;
4369 
4370 		hdd_debug("Only 2.4ghz channels, resetting BW to %d 2.4 cbmode %d",
4371 			  sap_config->acs_cfg.ch_width,
4372 			  channel_bonding_mode_2g);
4373 	}
4374 
4375 	sap_config->acs_cfg.ch_width = wlan_hdd_update_bw_from_mlme(hdd_ctx,
4376 								    sap_config);
4377 
4378 	hdd_nofl_debug("ACS Config country %s ch_width %d hw_mode %d ACS_BW: %d HT: %d VHT: %d EHT: %d START_CH: %d END_CH: %d band %d last_scan_ageout_time %d",
4379 		       hdd_ctx->reg.alpha2, ch_width,
4380 		       sap_config->acs_cfg.hw_mode, sap_config->acs_cfg.ch_width,
4381 		       ht_enabled, vht_enabled, eht_enabled,
4382 		       sap_config->acs_cfg.start_ch_freq,
4383 		       sap_config->acs_cfg.end_ch_freq,
4384 		       sap_config->acs_cfg.band, last_scan_ageout_time);
4385 	host_log_acs_req_event(adapter->dev->name,
4386 			  csr_phy_mode_str(sap_config->acs_cfg.hw_mode),
4387 			  ch_width, ht_enabled, vht_enabled,
4388 			  sap_config->acs_cfg.start_ch_freq,
4389 			  sap_config->acs_cfg.end_ch_freq);
4390 
4391 	sap_config->acs_cfg.is_ht_enabled = ht_enabled;
4392 	sap_config->acs_cfg.is_vht_enabled = vht_enabled;
4393 	wlan_hdd_acs_set_eht_enabled(sap_config, eht_enabled);
4394 	sap_config->acs_cfg.last_scan_ageout_time = last_scan_ageout_time;
4395 
4396 	sap_dump_acs_channel(&sap_config->acs_cfg);
4397 
4398 	if (wlan_hdd_ll_lt_sap_get_valid_last_acs_freq(adapter)) {
4399 		ret = 0;
4400 		goto out;
4401 	}
4402 
4403 	qdf_status = ucfg_mlme_get_vendor_acs_support(hdd_ctx->psoc,
4404 						      &is_vendor_acs_support);
4405 	if (QDF_IS_STATUS_ERROR(qdf_status))
4406 		hdd_err("get_vendor_acs_support failed, set default");
4407 
4408 	/* Check if vendor specific acs is enabled */
4409 	if (is_vendor_acs_support)
4410 		ret = hdd_start_vendor_acs(adapter);
4411 	else
4412 		ret = wlan_hdd_cfg80211_start_acs(link_info);
4413 
4414 out:
4415 	if (ret == 0) {
4416 		temp_skbuff =
4417 			wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4418 								 NLMSG_HDRLEN);
4419 		if (temp_skbuff)
4420 			return wlan_cfg80211_vendor_cmd_reply(temp_skbuff);
4421 	}
4422 	qdf_atomic_set(&ap_ctx->acs_in_progress, 0);
4423 
4424 	return ret;
4425 }
4426 
4427 /**
4428  * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
4429  * @wiphy:  Linux wiphy struct pointer
4430  * @wdev:   Linux wireless device struct pointer
4431  * @data:   ACS information from hostapd
4432  * @data_len: ACS information len
4433  *
4434  * This function handle DO_ACS Vendor command from hostapd, parses ACS config
4435  * and starts ACS procedure.
4436  *
4437  * Return: ACS procedure start status
4438  */
4439 
4440 static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
4441 				    struct wireless_dev *wdev,
4442 				    const void *data, int data_len)
4443 {
4444 	int errno;
4445 	struct osif_vdev_sync *vdev_sync;
4446 
4447 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
4448 	if (errno)
4449 		return errno;
4450 
4451 	errno = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
4452 
4453 	osif_vdev_sync_op_stop(vdev_sync);
4454 
4455 	return errno;
4456 }
4457 
4458 void wlan_hdd_undo_acs(struct wlan_hdd_link_info *link_info)
4459 {
4460 	sap_undo_acs(WLAN_HDD_GET_SAP_CTX_PTR(link_info),
4461 		     &link_info->session.ap.sap_config);
4462 }
4463 
4464 /**
4465  * hdd_fill_acs_chan_freq() - Populate channel frequencies (MHz) selected in ACS
4466  * @hdd_ctx: pointer to hdd context
4467  * @sap_cfg: sap acs configuration
4468  * @vendor_event: output pointer to populate channel frequencies (MHz)
4469  *
4470  * Return: If populated successfully return 0 else negative value.
4471  */
4472 static int hdd_fill_acs_chan_freq(struct hdd_context *hdd_ctx,
4473 				  struct sap_config *sap_cfg,
4474 				  struct sk_buff *vendor_event)
4475 {
4476 	uint32_t id;
4477 	int errno;
4478 
4479 	id = QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY;
4480 	errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.pri_ch_freq);
4481 	if (errno) {
4482 		hdd_err("VENDOR_ATTR_ACS_PRIMARY_FREQUENCY put fail");
4483 		return errno;
4484 	}
4485 
4486 	id = QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY;
4487 	errno = nla_put_u32(vendor_event, id, sap_cfg->acs_cfg.ht_sec_ch_freq);
4488 	if (errno) {
4489 		hdd_err("VENDOR_ATTR_ACS_SECONDARY_FREQUENCY put fail");
4490 		return errno;
4491 	}
4492 
4493 	id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY;
4494 	errno = nla_put_u32(vendor_event, id,
4495 			    sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
4496 	if (errno) {
4497 		hdd_err("VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY put fail");
4498 		return errno;
4499 	}
4500 
4501 	id = QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY;
4502 	errno = nla_put_u32(vendor_event, id,
4503 			    sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
4504 	if (errno) {
4505 		hdd_err("VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY put fail");
4506 		return errno;
4507 	}
4508 
4509 	return 0;
4510 }
4511 
4512 static int hdd_get_acs_evt_data_len(struct sap_config *sap_cfg)
4513 {
4514 	uint32_t len = NLMSG_HDRLEN;
4515 
4516 	/* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL */
4517 	len += nla_total_size(sizeof(u8));
4518 
4519 	/* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL */
4520 	len += nla_total_size(sizeof(u8));
4521 
4522 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL */
4523 	len += nla_total_size(sizeof(u8));
4524 
4525 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL */
4526 	len += nla_total_size(sizeof(u8));
4527 
4528 	/* QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY */
4529 	len += nla_total_size(sizeof(u32));
4530 
4531 	/* QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY */
4532 	len += nla_total_size(sizeof(u32));
4533 
4534 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY */
4535 	len += nla_total_size(sizeof(u32));
4536 
4537 	/* QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY */
4538 	len += nla_total_size(sizeof(u32));
4539 
4540 	/* QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH */
4541 	len += nla_total_size(sizeof(u16));
4542 
4543 	/* QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE */
4544 	len += nla_total_size(sizeof(u8));
4545 
4546 	/* QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP */
4547 	if (sap_acs_is_puncture_applicable(&sap_cfg->acs_cfg))
4548 		len += nla_total_size(sizeof(u16));
4549 
4550 	return len;
4551 }
4552 
4553 #ifdef WLAN_FEATURE_11BE
4554 /**
4555  * wlan_hdd_acs_get_puncture_bitmap() - get puncture_bitmap for acs result
4556  * @acs_cfg: pointer to struct sap_acs_cfg
4557  *
4558  * Return: acs puncture bitmap
4559  */
4560 static uint16_t wlan_hdd_acs_get_puncture_bitmap(struct sap_acs_cfg *acs_cfg)
4561 {
4562 	if (sap_acs_is_puncture_applicable(acs_cfg))
4563 		return acs_cfg->acs_puncture_bitmap;
4564 
4565 	return 0;
4566 }
4567 #else
4568 static uint16_t wlan_hdd_acs_get_puncture_bitmap(struct sap_acs_cfg *acs_cfg)
4569 {
4570 	return 0;
4571 }
4572 #endif /* WLAN_FEATURE_11BE */
4573 
4574 void wlan_hdd_cfg80211_acs_ch_select_evt(struct wlan_hdd_link_info *link_info,
4575 					 bool store_acs_freq)
4576 {
4577 	struct hdd_adapter *adapter = link_info->adapter;
4578 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
4579 	struct sap_config *sap_cfg;
4580 	struct sk_buff *vendor_event;
4581 	int ret_val;
4582 	uint16_t ch_width;
4583 	uint8_t pri_channel;
4584 	uint8_t ht_sec_channel;
4585 	uint8_t vht_seg0_center_ch, vht_seg1_center_ch;
4586 	uint32_t id = QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX;
4587 	uint32_t len;
4588 	uint16_t puncture_bitmap;
4589 
4590 	qdf_atomic_set(&link_info->session.ap.acs_in_progress, 0);
4591 	qdf_event_set(&link_info->acs_complete_event);
4592 
4593 	sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(link_info))->sap_config;
4594 	len = hdd_get_acs_evt_data_len(sap_cfg);
4595 
4596 	if (store_acs_freq &&
4597 	    policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc,
4598 					 link_info->vdev_id)) {
4599 		sap_cfg->last_acs_freq = sap_cfg->acs_cfg.pri_ch_freq;
4600 		sap_cfg->last_acs_complete_time = qdf_get_time_of_the_day_ms();
4601 	}
4602 
4603 	vendor_event = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4604 							&adapter->wdev, len, id,
4605 							GFP_KERNEL);
4606 
4607 	if (!vendor_event) {
4608 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
4609 		return;
4610 	}
4611 
4612 	ret_val = hdd_fill_acs_chan_freq(hdd_ctx, sap_cfg, vendor_event);
4613 	if (ret_val) {
4614 		hdd_err("failed to put frequencies");
4615 		wlan_cfg80211_vendor_free_skb(vendor_event);
4616 		return;
4617 	}
4618 
4619 	pri_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
4620 					    sap_cfg->acs_cfg.pri_ch_freq);
4621 
4622 	ht_sec_channel = wlan_reg_freq_to_chan(hdd_ctx->pdev,
4623 					       sap_cfg->acs_cfg.ht_sec_ch_freq);
4624 
4625 	ret_val = nla_put_u8(vendor_event,
4626 				QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
4627 				pri_channel);
4628 	if (ret_val) {
4629 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
4630 		wlan_cfg80211_vendor_free_skb(vendor_event);
4631 		return;
4632 	}
4633 
4634 	ret_val = nla_put_u8(vendor_event,
4635 			     QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
4636 			     ht_sec_channel);
4637 	if (ret_val) {
4638 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
4639 		wlan_cfg80211_vendor_free_skb(vendor_event);
4640 		return;
4641 	}
4642 	vht_seg0_center_ch = wlan_reg_freq_to_chan(
4643 				hdd_ctx->pdev,
4644 				sap_cfg->acs_cfg.vht_seg0_center_ch_freq);
4645 	ret_val = nla_put_u8(vendor_event,
4646 			QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
4647 			vht_seg0_center_ch);
4648 	if (ret_val) {
4649 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
4650 		wlan_cfg80211_vendor_free_skb(vendor_event);
4651 		return;
4652 	}
4653 	vht_seg1_center_ch = wlan_reg_freq_to_chan(
4654 				hdd_ctx->pdev,
4655 				sap_cfg->acs_cfg.vht_seg1_center_ch_freq);
4656 	ret_val = nla_put_u8(vendor_event,
4657 			QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
4658 			vht_seg1_center_ch);
4659 	if (ret_val) {
4660 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
4661 		wlan_cfg80211_vendor_free_skb(vendor_event);
4662 		return;
4663 	}
4664 
4665 	if (wlan_hdd_is_sap_acs_ch_width_320(sap_cfg))
4666 		ch_width = 320;
4667 	else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
4668 		ch_width = 160;
4669 	else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
4670 		ch_width = 80;
4671 	else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
4672 		ch_width = 40;
4673 	else
4674 		ch_width = 20;
4675 
4676 	ret_val = nla_put_u16(vendor_event,
4677 				QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
4678 				ch_width);
4679 	if (ret_val) {
4680 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
4681 		wlan_cfg80211_vendor_free_skb(vendor_event);
4682 		return;
4683 	}
4684 	if (WLAN_REG_IS_24GHZ_CH_FREQ(sap_cfg->acs_cfg.pri_ch_freq))
4685 		ret_val = nla_put_u8(vendor_event,
4686 					QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
4687 					QCA_ACS_MODE_IEEE80211G);
4688 	else
4689 		ret_val = nla_put_u8(vendor_event,
4690 					QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
4691 					QCA_ACS_MODE_IEEE80211A);
4692 
4693 	if (ret_val) {
4694 		hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
4695 		wlan_cfg80211_vendor_free_skb(vendor_event);
4696 		return;
4697 	}
4698 
4699 	puncture_bitmap = wlan_hdd_acs_get_puncture_bitmap(&sap_cfg->acs_cfg);
4700 	if (sap_acs_is_puncture_applicable(&sap_cfg->acs_cfg)) {
4701 		ret_val = nla_put_u16(vendor_event,
4702 				      QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP,
4703 				      puncture_bitmap);
4704 		if (ret_val) {
4705 			hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP put fail");
4706 			wlan_cfg80211_vendor_free_skb(vendor_event);
4707 			return;
4708 		}
4709 	}
4710 
4711 	hdd_debug("ACS result for %s: PRI_CH_FREQ: %d SEC_CH_FREQ: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d punc support: %d punc bitmap: %d",
4712 		  adapter->dev->name, sap_cfg->acs_cfg.pri_ch_freq,
4713 		  sap_cfg->acs_cfg.ht_sec_ch_freq,
4714 		  sap_cfg->acs_cfg.vht_seg0_center_ch_freq,
4715 		  sap_cfg->acs_cfg.vht_seg1_center_ch_freq, ch_width,
4716 		  sap_acs_is_puncture_applicable(&sap_cfg->acs_cfg),
4717 		  puncture_bitmap);
4718 
4719 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
4720 }
4721 
4722 /**
4723  * hdd_is_wlm_latency_manager_supported - Checks if WLM Latency manager is
4724  *                                        supported
4725  * @hdd_ctx: The HDD context
4726  *
4727  * Return: True if supported, false otherwise
4728  */
4729 static inline
4730 bool hdd_is_wlm_latency_manager_supported(struct hdd_context *hdd_ctx)
4731 {
4732 	bool latency_enable;
4733 
4734 	if (QDF_IS_STATUS_ERROR(ucfg_mlme_get_latency_enable
4735 				(hdd_ctx->psoc, &latency_enable)))
4736 		return false;
4737 
4738 	if (latency_enable &&
4739 	    sme_is_feature_supported_by_fw(VDEV_LATENCY_CONFIG))
4740 		return true;
4741 	else
4742 		return false;
4743 }
4744 
4745 static int
4746 __wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
4747 					 struct wireless_dev *wdev,
4748 					 const void *data,
4749 					 int data_len)
4750 {
4751 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
4752 	struct sk_buff *skb = NULL;
4753 	uint32_t fset = 0;
4754 	int ret;
4755 #ifdef FEATURE_WLAN_TDLS
4756 	bool bvalue;
4757 #endif
4758 	uint32_t fine_time_meas_cap;
4759 
4760 	/* ENTER_DEV() intentionally not used in a frequently invoked API */
4761 
4762 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4763 		hdd_err("Command not allowed in FTM mode");
4764 		return -EPERM;
4765 	}
4766 
4767 	ret = wlan_hdd_validate_context(hdd_ctx);
4768 	if (ret)
4769 		return ret;
4770 
4771 	if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
4772 		hdd_debug("Infra Station mode is supported by driver");
4773 		fset |= WIFI_FEATURE_INFRA;
4774 	}
4775 	if (true == hdd_is_5g_supported(hdd_ctx)) {
4776 		hdd_debug("INFRA_5G is supported by firmware");
4777 		fset |= WIFI_FEATURE_INFRA_5G;
4778 	}
4779 #ifdef WLAN_FEATURE_P2P
4780 	if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
4781 	    (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
4782 		hdd_debug("WiFi-Direct is supported by driver");
4783 		fset |= WIFI_FEATURE_P2P;
4784 	}
4785 #endif
4786 	fset |= WIFI_FEATURE_SOFT_AP;
4787 
4788 	/* HOTSPOT is a supplicant feature, enable it by default */
4789 	fset |= WIFI_FEATURE_HOTSPOT;
4790 
4791 	if (ucfg_extscan_get_enable(hdd_ctx->psoc) &&
4792 	    sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
4793 		hdd_debug("EXTScan is supported by firmware");
4794 		fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
4795 	}
4796 	if (wlan_hdd_nan_is_supported(hdd_ctx)) {
4797 		hdd_debug("NAN is supported by firmware");
4798 		fset |= WIFI_FEATURE_NAN;
4799 	}
4800 
4801 	ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, &fine_time_meas_cap);
4802 
4803 	if (sme_is_feature_supported_by_fw(RTT) &&
4804 	    rtt_is_enabled(fine_time_meas_cap)) {
4805 		hdd_debug("RTT is supported by firmware and driver: %x",
4806 			  fine_time_meas_cap);
4807 		fset |= WIFI_FEATURE_D2D_RTT;
4808 		fset |= WIFI_FEATURE_D2AP_RTT;
4809 	}
4810 #ifdef FEATURE_WLAN_SCAN_PNO
4811 	if (ucfg_scan_get_pno_scan_support(hdd_ctx->psoc) &&
4812 	    sme_is_feature_supported_by_fw(PNO)) {
4813 		hdd_debug("PNO is supported by firmware");
4814 		fset |= WIFI_FEATURE_PNO;
4815 	}
4816 #endif
4817 	if (ucfg_policy_mgr_get_dual_sta_feature(hdd_ctx->psoc))
4818 		fset |= WIFI_FEATURE_ADDITIONAL_STA;
4819 
4820 #ifdef FEATURE_WLAN_TDLS
4821 	cfg_tdls_get_support_enable(hdd_ctx->psoc, &bvalue);
4822 	if ((bvalue) && sme_is_feature_supported_by_fw(TDLS)) {
4823 		hdd_debug("TDLS is supported by firmware");
4824 		fset |= WIFI_FEATURE_TDLS;
4825 	}
4826 
4827 	cfg_tdls_get_off_channel_enable(hdd_ctx->psoc, &bvalue);
4828 	if (sme_is_feature_supported_by_fw(TDLS) &&
4829 	    bvalue && sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
4830 		hdd_debug("TDLS off-channel is supported by firmware");
4831 		fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
4832 	}
4833 #endif
4834 	fset |= WIFI_FEATURE_AP_STA;
4835 	fset |= WIFI_FEATURE_RSSI_MONITOR;
4836 	fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
4837 	fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
4838 	fset |= WIFI_FEATURE_CONFIG_NDO;
4839 
4840 	if (hdd_link_layer_stats_supported())
4841 		fset |= WIFI_FEATURE_LINK_LAYER_STATS;
4842 
4843 	if (hdd_roaming_supported(hdd_ctx))
4844 		fset |= WIFI_FEATURE_CONTROL_ROAMING;
4845 
4846 	if (hdd_scan_random_mac_addr_supported())
4847 		fset |= WIFI_FEATURE_SCAN_RAND;
4848 
4849 	if (hdd_is_wlm_latency_manager_supported(hdd_ctx))
4850 		fset |= WIFI_FEATURE_SET_LATENCY_MODE;
4851 
4852 	if (hdd_dynamic_mac_addr_supported(hdd_ctx))
4853 		fset |= WIFI_FEATURE_DYNAMIC_SET_MAC;
4854 
4855 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
4856 						       NLMSG_HDRLEN);
4857 	if (!skb) {
4858 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
4859 		return -EINVAL;
4860 	}
4861 	hdd_debug("Supported Features : 0x%x", fset);
4862 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
4863 		hdd_err("nla put fail");
4864 		goto nla_put_failure;
4865 	}
4866 	ret = wlan_cfg80211_vendor_cmd_reply(skb);
4867 	return ret;
4868 nla_put_failure:
4869 	wlan_cfg80211_vendor_free_skb(skb);
4870 	return -EINVAL;
4871 }
4872 
4873 /**
4874  * wlan_hdd_cfg80211_get_supported_features() - get supported features
4875  * @wiphy:   pointer to wireless wiphy structure.
4876  * @wdev:    pointer to wireless_dev structure.
4877  * @data:    Pointer to the data to be passed via vendor interface
4878  * @data_len:Length of the data to be passed
4879  *
4880  * Return:   Return the Success or Failure code.
4881  */
4882 static int
4883 wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
4884 					struct wireless_dev *wdev,
4885 					const void *data, int data_len)
4886 {
4887 	struct osif_psoc_sync *psoc_sync;
4888 	int errno;
4889 
4890 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
4891 	if (errno)
4892 		return errno;
4893 
4894 	errno = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
4895 							   data, data_len);
4896 
4897 	osif_psoc_sync_op_stop(psoc_sync);
4898 
4899 	return errno;
4900 }
4901 
4902 /**
4903  * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
4904  * @wiphy:   pointer to wireless wiphy structure.
4905  * @wdev:    pointer to wireless_dev structure.
4906  * @data:    Pointer to the data to be passed via vendor interface
4907  * @data_len:Length of the data to be passed
4908  *
4909  * Set the MAC address that is to be used for scanning.
4910  *
4911  * Return:   Return the Success or Failure code.
4912  */
4913 static int
4914 __wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
4915 					 struct wireless_dev *wdev,
4916 					 const void *data,
4917 					 int data_len)
4918 {
4919 	struct scan_mac_oui scan_mac_oui = { {0} };
4920 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
4921 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
4922 	QDF_STATUS status;
4923 	int ret, len;
4924 	struct net_device *ndev = wdev->netdev;
4925 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
4926 	mac_handle_t mac_handle;
4927 	bool mac_spoofing_enabled;
4928 
4929 	hdd_enter_dev(wdev->netdev);
4930 
4931 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4932 		hdd_err("Command not allowed in FTM mode");
4933 		return -EPERM;
4934 	}
4935 
4936 	ret = wlan_hdd_validate_context(hdd_ctx);
4937 	if (ret)
4938 		return ret;
4939 
4940 	mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
4941 	if (!mac_spoofing_enabled) {
4942 		hdd_debug("MAC address spoofing is not enabled");
4943 		return -ENOTSUPP;
4944 	}
4945 
4946 	/*
4947 	 * audit note: it is ok to pass a NULL policy here since only
4948 	 * one attribute is parsed and it is explicitly validated
4949 	 */
4950 	if (wlan_cfg80211_nla_parse(tb,
4951 				  QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
4952 				  data, data_len, NULL)) {
4953 		hdd_err("Invalid ATTR");
4954 		return -EINVAL;
4955 	}
4956 
4957 	if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
4958 		hdd_err("attr mac oui failed");
4959 		return -EINVAL;
4960 	}
4961 
4962 	len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
4963 	if (len != sizeof(scan_mac_oui.oui)) {
4964 		hdd_err("attr mac oui invalid size %d expected %zu",
4965 			len, sizeof(scan_mac_oui.oui));
4966 		return -EINVAL;
4967 	}
4968 
4969 	nla_memcpy(scan_mac_oui.oui,
4970 		   tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
4971 		   sizeof(scan_mac_oui.oui));
4972 
4973 	/* populate rest of scan_mac_oui for mac addr randomization */
4974 	scan_mac_oui.vdev_id = adapter->deflink->vdev_id;
4975 	scan_mac_oui.enb_probe_req_sno_randomization = true;
4976 
4977 	hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d",
4978 		  scan_mac_oui.oui[0], scan_mac_oui.oui[1],
4979 		  scan_mac_oui.oui[2], scan_mac_oui.vdev_id);
4980 
4981 	hdd_update_ie_allowlist_attr(&scan_mac_oui.ie_allowlist, hdd_ctx);
4982 
4983 	mac_handle = hdd_ctx->mac_handle;
4984 	status = sme_set_scanning_mac_oui(mac_handle, &scan_mac_oui);
4985 	if (!QDF_IS_STATUS_SUCCESS(status))
4986 		hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
4987 
4988 	return qdf_status_to_os_return(status);
4989 }
4990 
4991 /**
4992  * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
4993  * @wiphy:   pointer to wireless wiphy structure.
4994  * @wdev:    pointer to wireless_dev structure.
4995  * @data:    Pointer to the data to be passed via vendor interface
4996  * @data_len:Length of the data to be passed
4997  *
4998  * Set the MAC address that is to be used for scanning.  This is an
4999  * SSR-protecting wrapper function.
5000  *
5001  * Return:   Return the Success or Failure code.
5002  */
5003 static int
5004 wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
5005 				       struct wireless_dev *wdev,
5006 				       const void *data,
5007 				       int data_len)
5008 {
5009 	int errno;
5010 	struct osif_vdev_sync *vdev_sync;
5011 
5012 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
5013 	if (errno)
5014 		return errno;
5015 
5016 	errno = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
5017 							 data, data_len);
5018 
5019 	osif_vdev_sync_op_stop(vdev_sync);
5020 
5021 	return errno;
5022 }
5023 
5024 #define NUM_BITS_IN_BYTE       8
5025 
5026 /**
5027  * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
5028  * @feature_flags: pointer to the byte array of features.
5029  * @feature: Feature to be turned ON in the byte array.
5030  *
5031  * Return: None
5032  *
5033  * This is called to turn ON or SET the feature flag for the requested feature.
5034  **/
5035 static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
5036 					  uint8_t feature)
5037 {
5038 	uint32_t index;
5039 	uint8_t bit_mask;
5040 
5041 	index = feature / NUM_BITS_IN_BYTE;
5042 	bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
5043 	feature_flags[index] |= bit_mask;
5044 }
5045 
5046 /**
5047  * wlan_hdd_set_ndi_feature() - Set NDI related features
5048  * @feature_flags: pointer to the byte array of features.
5049  *
5050  * Return: None
5051  **/
5052 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0))
5053 static void wlan_hdd_set_ndi_feature(uint8_t *feature_flags)
5054 {
5055 	wlan_hdd_cfg80211_set_feature(feature_flags,
5056 				      QCA_WLAN_VENDOR_FEATURE_USE_ADD_DEL_VIRTUAL_INTF_FOR_NDI);
5057 }
5058 #else
5059 static inline void wlan_hdd_set_ndi_feature(uint8_t *feature_flags)
5060 {
5061 }
5062 #endif
5063 
5064 static inline void wlan_hdd_set_ll_lt_sap_feature(struct wlan_objmgr_psoc *psoc,
5065 						  uint8_t *feature_flags)
5066 {
5067 	/* To Do: Once FW feature capability changes for ll_lt_sap feature are
5068 	 * merged, then this feature will be set based on that feature set
5069 	 * capability
5070 	 */
5071 	if (!ucfg_is_ll_lt_sap_supported(psoc)) {
5072 		hdd_debug("ll_lt_sap feature is disabled in FW");
5073 		return;
5074 	}
5075 	wlan_hdd_cfg80211_set_feature(feature_flags,
5076 				      QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN);
5077 }
5078 
5079 #define MAX_CONCURRENT_CHAN_ON_24G    2
5080 #define MAX_CONCURRENT_CHAN_ON_5G     2
5081 
5082 /**
5083  * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
5084  * @wiphy: pointer to wireless wiphy structure.
5085  * @wdev: pointer to wireless_dev structure.
5086  * @data: Pointer to the data to be passed via vendor interface
5087  * @data_len:Length of the data to be passed
5088  *
5089  * This is called when wlan driver needs to send supported feature set to
5090  * supplicant upon a request/query from the supplicant.
5091  *
5092  * Return: Return the Success or Failure code.
5093  **/
5094 static int
5095 __wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
5096 				 struct wireless_dev *wdev,
5097 				 const void *data, int data_len)
5098 {
5099 	struct sk_buff *skb = NULL;
5100 	uint32_t dbs_capability = 0;
5101 	bool one_by_one_dbs, two_by_two_dbs;
5102 	bool value, twt_req, twt_res;
5103 	QDF_STATUS ret = QDF_STATUS_E_FAILURE;
5104 	QDF_STATUS status;
5105 	int ret_val;
5106 	uint8_t max_assoc_cnt = 0;
5107 	uint8_t max_str_link_count = 0;
5108 
5109 	uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
5110 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
5111 
5112 	hdd_enter_dev(wdev->netdev);
5113 
5114 	ret_val = wlan_hdd_validate_context(hdd_ctx);
5115 	if (ret_val)
5116 		return ret_val;
5117 
5118 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5119 		hdd_err("Command not allowed in FTM mode");
5120 		return -EPERM;
5121 	}
5122 
5123 	if (roaming_offload_enabled(hdd_ctx)) {
5124 		hdd_debug("Key Mgmt Offload is supported");
5125 		wlan_hdd_cfg80211_set_feature(feature_flags,
5126 				QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
5127 	}
5128 
5129 	wlan_hdd_cfg80211_set_feature(feature_flags,
5130 				QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
5131 	if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx->psoc))
5132 		wlan_hdd_cfg80211_set_feature(feature_flags,
5133 			QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
5134 
5135 	if (policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc))
5136 		wlan_hdd_cfg80211_set_feature(feature_flags,
5137 			QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS);
5138 
5139 	if (wma_is_p2p_lo_capable())
5140 		wlan_hdd_cfg80211_set_feature(feature_flags,
5141 			QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
5142 
5143 	value = false;
5144 	status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc, &value);
5145 	if (QDF_IS_STATUS_ERROR(status))
5146 		hdd_err("could not get OCE STA enable info");
5147 	if (value)
5148 		wlan_hdd_cfg80211_set_feature(feature_flags,
5149 					      QCA_WLAN_VENDOR_FEATURE_OCE_STA);
5150 
5151 	value = false;
5152 	status = ucfg_mlme_get_oce_sap_enabled_info(hdd_ctx->psoc, &value);
5153 	if (QDF_IS_STATUS_ERROR(status))
5154 		hdd_err("could not get OCE SAP enable info");
5155 	if (value)
5156 		wlan_hdd_cfg80211_set_feature(feature_flags,
5157 					  QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
5158 
5159 	value = false;
5160 	status = ucfg_mlme_get_adaptive11r_enabled(hdd_ctx->psoc, &value);
5161 	if (QDF_IS_STATUS_ERROR(status))
5162 		hdd_err("could not get FT-Adaptive 11R info");
5163 	if (value) {
5164 		hdd_debug("FT-Adaptive 11R is Enabled");
5165 		wlan_hdd_cfg80211_set_feature(feature_flags,
5166 					  QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R);
5167 	}
5168 
5169 	hdd_get_twt_requestor(hdd_ctx->psoc, &twt_req);
5170 	hdd_get_twt_responder(hdd_ctx->psoc, &twt_res);
5171 	hdd_debug("twt_req:%d twt_res:%d", twt_req, twt_res);
5172 
5173 	if (twt_req || twt_res) {
5174 		wlan_hdd_cfg80211_set_feature(feature_flags,
5175 					      QCA_WLAN_VENDOR_FEATURE_TWT);
5176 
5177 		wlan_hdd_cfg80211_set_feature(
5178 				feature_flags,
5179 				QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT);
5180 	}
5181 
5182 	/* Check the kernel version for upstream commit aced43ce780dc5 that
5183 	 * has support for processing user cell_base hints when wiphy is
5184 	 * self managed or check the backport flag for the same.
5185 	 */
5186 #if defined CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED || \
5187 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
5188 	wlan_hdd_cfg80211_set_feature(feature_flags,
5189 			QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY);
5190 #endif
5191 
5192 	if (wlan_hdd_thermal_config_support())
5193 		wlan_hdd_cfg80211_set_feature(feature_flags,
5194 					QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG);
5195 
5196 	wlan_hdd_set_ndi_feature(feature_flags);
5197 	wlan_hdd_cfg80211_set_feature(
5198 				feature_flags,
5199 				QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST);
5200 	wlan_wifi_pos_cfg80211_set_features(hdd_ctx->psoc, feature_flags);
5201 	wlan_hdd_set_ll_lt_sap_feature(hdd_ctx->psoc, feature_flags);
5202 
5203 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5204 						       sizeof(feature_flags) +
5205 						       NLMSG_HDRLEN);
5206 
5207 	if (!skb) {
5208 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
5209 		return -ENOMEM;
5210 	}
5211 
5212 	if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
5213 			sizeof(feature_flags), feature_flags))
5214 		goto nla_put_failure;
5215 
5216 	ret = policy_mgr_get_dbs_hw_modes(hdd_ctx->psoc,
5217 					  &one_by_one_dbs, &two_by_two_dbs);
5218 	if (QDF_STATUS_SUCCESS == ret) {
5219 		if (one_by_one_dbs)
5220 			dbs_capability = DRV_DBS_CAPABILITY_1X1;
5221 
5222 		if (two_by_two_dbs)
5223 			dbs_capability = DRV_DBS_CAPABILITY_2X2;
5224 
5225 		if (!one_by_one_dbs && !two_by_two_dbs)
5226 			dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
5227 	} else {
5228 		hdd_err("wma_get_dbs_hw_mode failed");
5229 		dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
5230 	}
5231 
5232 	hdd_debug("dbs_capability is %d", dbs_capability);
5233 
5234 	if (nla_put_u32(skb,
5235 			QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
5236 			dbs_capability))
5237 		goto nla_put_failure;
5238 
5239 
5240 	if (nla_put_u32(skb,
5241 			QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
5242 			MAX_CONCURRENT_CHAN_ON_24G))
5243 		goto nla_put_failure;
5244 
5245 	if (nla_put_u32(skb,
5246 			QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
5247 			MAX_CONCURRENT_CHAN_ON_5G))
5248 		goto nla_put_failure;
5249 
5250 	max_assoc_cnt = wlan_mlme_get_sta_mlo_conn_max_num(hdd_ctx->psoc);
5251 	if (max_assoc_cnt) {
5252 		if (nla_put_u8(
5253 			skb,
5254 			QCA_WLAN_VENDOR_ATTR_MLO_CAPABILITY_MAX_ASSOCIATION_COUNT,
5255 			max_assoc_cnt))
5256 			goto nla_put_failure;
5257 
5258 		max_str_link_count = DEFAULT_MAX_STR_LINK_COUNT;
5259 
5260 		if (policy_mgr_is_hw_dbs_capable(hdd_ctx->psoc) ||
5261 		    policy_mgr_is_hw_sbs_capable(hdd_ctx->psoc))
5262 			max_str_link_count = MAX_STR_LINK_COUNT;
5263 
5264 		if (nla_put_u8(skb,
5265 			       QCA_WLAN_VENDOR_ATTR_MLO_CAPABILITY_MAX_STR_LINK_COUNT,
5266 			       max_str_link_count))
5267 			goto nla_put_failure;
5268 	}
5269 
5270 	hdd_debug("max_assoc_cnt %d max_str_link_count %d",
5271 		  max_assoc_cnt, max_str_link_count);
5272 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
5273 			   feature_flags, sizeof(feature_flags));
5274 
5275 	return wlan_cfg80211_vendor_cmd_reply(skb);
5276 
5277 nla_put_failure:
5278 	wlan_cfg80211_vendor_free_skb(skb);
5279 	return -EINVAL;
5280 }
5281 
5282 /**
5283  * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
5284  * @wiphy:   pointer to wireless wiphy structure.
5285  * @wdev:    pointer to wireless_dev structure.
5286  * @data:    Pointer to the data to be passed via vendor interface
5287  * @data_len:Length of the data to be passed
5288  *
5289  * This is called when wlan driver needs to send supported feature set to
5290  * supplicant upon a request/query from the supplicant.
5291  *
5292  * Return:   Return the Success or Failure code.
5293  */
5294 static int
5295 wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
5296 		struct wireless_dev *wdev,
5297 		const void *data, int data_len)
5298 {
5299 	struct osif_psoc_sync *psoc_sync;
5300 	int errno;
5301 
5302 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
5303 	if (errno)
5304 		return errno;
5305 
5306 	errno = __wlan_hdd_cfg80211_get_features(wiphy, wdev, data, data_len);
5307 
5308 	osif_psoc_sync_op_stop(psoc_sync);
5309 
5310 	return errno;
5311 }
5312 
5313 #define PARAM_NUM_NW \
5314 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
5315 #define PARAM_SET_BSSID \
5316 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
5317 #define PARAM_SET_BSSID_HINT \
5318 		QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT
5319 #define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
5320 #define PARAM_LIST_SSID  QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
5321 #define MAX_ROAMING_PARAM \
5322 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
5323 #define PARAM_NUM_BSSID \
5324 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
5325 #define PARAM_BSSID_PREFS \
5326 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
5327 #define PARAM_ROAM_BSSID \
5328 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
5329 #define PARAM_RSSI_MODIFIER \
5330 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
5331 #define PARAMS_NUM_BSSID \
5332 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
5333 #define PARAM_BSSID_PARAMS \
5334 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
5335 #define PARAM_A_BAND_BOOST_THLD \
5336 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
5337 #define PARAM_A_BAND_PELT_THLD \
5338 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
5339 #define PARAM_A_BAND_BOOST_FACTOR \
5340 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
5341 #define PARAM_A_BAND_PELT_FACTOR \
5342 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
5343 #define PARAM_A_BAND_MAX_BOOST \
5344 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
5345 #define PARAM_ROAM_HISTERESYS \
5346 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
5347 #define PARAM_RSSI_TRIGGER \
5348 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
5349 #define PARAM_ROAM_ENABLE \
5350 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
5351 #define PARAM_ROAM_CONTROL_CONFIG \
5352 	QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL
5353 #define PARAM_FREQ_LIST_SCHEME \
5354 	QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME
5355 #define PARAM_FREQ_LIST_SCHEME_MAX \
5356 	QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_MAX
5357 #define PARAM_SCAN_FREQ_LIST \
5358 	QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST
5359 #define PARAM_SCAN_FREQ_LIST_TYPE \
5360 	QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE
5361 #define PARAM_CAND_SEL_CRITERIA_MAX \
5362 	QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_MAX
5363 #define PARAM_CAND_SEL_SCORE_RSSI \
5364 	QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_RSSI
5365 
5366 const struct nla_policy wlan_hdd_set_roam_param_policy[
5367 			MAX_ROAMING_PARAM + 1] = {
5368 	[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
5369 	[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
5370 	[PARAM_NUM_NW] = {.type = NLA_U32},
5371 	[PARAM_SSID_LIST] = { .type = NLA_NESTED },
5372 	[PARAM_LIST_SSID] = { .type = NLA_BINARY },
5373 	[PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
5374 	[PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
5375 	[PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
5376 	[PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
5377 	[PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
5378 	[PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
5379 	[PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
5380 	[PARAM_ROAM_ENABLE] = {	.type = NLA_S32},
5381 	[PARAM_BSSID_PREFS] = { .type = NLA_NESTED },
5382 	[PARAM_NUM_BSSID] = {.type = NLA_U32},
5383 	[PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
5384 	[PARAM_BSSID_PARAMS] = {.type = NLA_NESTED},
5385 	[PARAMS_NUM_BSSID] = {.type = NLA_U32},
5386 	[PARAM_ROAM_BSSID] = VENDOR_NLA_POLICY_MAC_ADDR,
5387 	[PARAM_SET_BSSID] = VENDOR_NLA_POLICY_MAC_ADDR,
5388 	[PARAM_SET_BSSID_HINT] = {.type = NLA_FLAG},
5389 	[PARAM_ROAM_CONTROL_CONFIG] = {.type = NLA_NESTED},
5390 };
5391 
5392 /**
5393  * hdd_set_allow_list() - parse allow list
5394  * @hdd_ctx: HDD context
5395  * @rso_config: rso config
5396  * @tb: list of attributes
5397  * @vdev_id: vdev id
5398  * @rso_usr_cfg: roam userspace params
5399  *
5400  * Return: 0 on success; error number on failure
5401  */
5402 static int hdd_set_allow_list(struct hdd_context *hdd_ctx,
5403 			      struct rso_config_params *rso_config,
5404 			      struct nlattr **tb, uint8_t vdev_id,
5405 			      struct rso_user_config *rso_usr_cfg)
5406 {
5407 	int rem, i;
5408 	uint32_t buf_len = 0, count;
5409 	struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
5410 	struct nlattr *curr_attr = NULL;
5411 	mac_handle_t mac_handle;
5412 	struct wlan_ssid *ssid;
5413 
5414 	i = 0;
5415 	if (tb[PARAM_NUM_NW]) {
5416 		count = nla_get_u32(tb[PARAM_NUM_NW]);
5417 	} else {
5418 		hdd_err("Number of networks is not provided");
5419 		goto fail;
5420 	}
5421 
5422 	if (count && tb[PARAM_SSID_LIST]) {
5423 		nla_for_each_nested(curr_attr,
5424 				    tb[PARAM_SSID_LIST], rem) {
5425 			if (i == MAX_SSID_ALLOWED_LIST) {
5426 				hdd_err("Excess MAX_SSID_ALLOWED_LIST");
5427 				goto fail;
5428 			}
5429 			if (wlan_cfg80211_nla_parse(tb2,
5430 					QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
5431 					nla_data(curr_attr),
5432 					nla_len(curr_attr),
5433 					wlan_hdd_set_roam_param_policy)) {
5434 				hdd_err("nla_parse failed");
5435 				goto fail;
5436 			}
5437 			/* Parse and Fetch allowed SSID list*/
5438 			if (!tb2[PARAM_LIST_SSID]) {
5439 				hdd_err("attr allowed ssid failed");
5440 				goto fail;
5441 			}
5442 			buf_len = nla_len(tb2[PARAM_LIST_SSID]);
5443 			/*
5444 			 * Upper Layers include a null termination
5445 			 * character. Check for the actual permissible
5446 			 * length of SSID and also ensure not to copy
5447 			 * the NULL termination character to the driver
5448 			 * buffer.
5449 			 */
5450 			if (buf_len <= 1 || (buf_len - 1) > WLAN_SSID_MAX_LEN) {
5451 				hdd_err("Invalid buffer length");
5452 				continue;
5453 			}
5454 
5455 			ssid = &rso_usr_cfg->ssid_allowed_list[i];
5456 			nla_memcpy(ssid->ssid,
5457 				   tb2[PARAM_LIST_SSID], buf_len - 1);
5458 			ssid->length = buf_len - 1;
5459 			hdd_debug("SSID[%d]: " QDF_SSID_FMT ",length = %d", i,
5460 				  QDF_SSID_REF(ssid->length, ssid->ssid),
5461 				  rso_usr_cfg->ssid_allowed_list[i].length);
5462 			i++;
5463 		}
5464 	}
5465 
5466 	if (i != count) {
5467 		hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
5468 		goto fail;
5469 	}
5470 
5471 	rso_usr_cfg->num_ssid_allowed_list = i;
5472 	hdd_debug("Num of Allowed SSID %d", rso_usr_cfg->num_ssid_allowed_list);
5473 	mac_handle = hdd_ctx->mac_handle;
5474 	sme_update_roam_params(mac_handle, vdev_id, rso_config, rso_usr_cfg,
5475 			       REASON_ROAM_SET_SSID_ALLOWED);
5476 	return 0;
5477 
5478 fail:
5479 	return -EINVAL;
5480 }
5481 
5482 /**
5483  * hdd_set_bssid_prefs() - parse set bssid prefs
5484  * @hdd_ctx:        HDD context
5485  * @rso_config: rso config
5486  * @tb:            list of attributes
5487  * @vdev_id:    vdev id
5488  *
5489  * Return: 0 on success; error number on failure
5490  */
5491 static int hdd_set_bssid_prefs(struct hdd_context *hdd_ctx,
5492 			       struct rso_config_params *rso_config,
5493 			       struct nlattr **tb, uint8_t vdev_id)
5494 {
5495 	int rem, i;
5496 	uint32_t count;
5497 	struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
5498 	struct nlattr *curr_attr = NULL;
5499 	mac_handle_t mac_handle;
5500 
5501 	/* Parse and fetch number of preferred BSSID */
5502 	if (!tb[PARAM_NUM_BSSID]) {
5503 		hdd_err("attr num of preferred bssid failed");
5504 		goto fail;
5505 	}
5506 	count = nla_get_u32(tb[PARAM_NUM_BSSID]);
5507 	if (count > MAX_BSSID_FAVORED) {
5508 		hdd_err("Preferred BSSID count %u exceeds max %u",
5509 			count, MAX_BSSID_FAVORED);
5510 		goto fail;
5511 	}
5512 	hdd_debug("Num of Preferred BSSID (%d)", count);
5513 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
5514 		hdd_err("attr Preferred BSSID failed");
5515 		goto fail;
5516 	}
5517 
5518 	i = 0;
5519 	nla_for_each_nested(curr_attr,
5520 		tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
5521 		rem) {
5522 		if (i == count) {
5523 			hdd_warn("Ignoring excess Preferred BSSID");
5524 			break;
5525 		}
5526 
5527 		if (wlan_cfg80211_nla_parse(tb2,
5528 					 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
5529 					 nla_data(curr_attr),
5530 					 nla_len(curr_attr),
5531 					 wlan_hdd_set_roam_param_policy)) {
5532 			hdd_err("nla_parse failed");
5533 			goto fail;
5534 		}
5535 		/* Parse and fetch MAC address */
5536 		if (!tb2[PARAM_ROAM_BSSID]) {
5537 			hdd_err("attr mac address failed");
5538 			goto fail;
5539 		}
5540 		nla_memcpy(rso_config->bssid_favored[i].bytes,
5541 			  tb2[PARAM_ROAM_BSSID],
5542 			  QDF_MAC_ADDR_SIZE);
5543 		hdd_debug(QDF_MAC_ADDR_FMT,
5544 			  QDF_MAC_ADDR_REF(rso_config->bssid_favored[i].bytes));
5545 		/* Parse and fetch preference factor*/
5546 		if (!tb2[PARAM_RSSI_MODIFIER]) {
5547 			hdd_err("BSSID Preference score failed");
5548 			goto fail;
5549 		}
5550 		rso_config->bssid_favored_factor[i] = nla_get_u32(
5551 			tb2[PARAM_RSSI_MODIFIER]);
5552 		hdd_debug("BSSID Preference score (%d)",
5553 			  rso_config->bssid_favored_factor[i]);
5554 		i++;
5555 	}
5556 	if (i < count)
5557 		hdd_warn("Num Preferred BSSID %u less than expected %u",
5558 				 i, count);
5559 
5560 	rso_config->num_bssid_favored = i;
5561 	mac_handle = hdd_ctx->mac_handle;
5562 	sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
5563 			       REASON_ROAM_SET_FAVORED_BSSID);
5564 
5565 	return 0;
5566 
5567 fail:
5568 	return -EINVAL;
5569 }
5570 
5571 /**
5572  * hdd_set_denylist_bssid() - parse set denylist bssid
5573  * @hdd_ctx:        HDD context
5574  * @rso_config:   roam params
5575  * @tb:            list of attributes
5576  * @vdev_id:    vdev id
5577  *
5578  * Return: 0 on success; error number on failure
5579  */
5580 static int hdd_set_denylist_bssid(struct hdd_context *hdd_ctx,
5581 				  struct rso_config_params *rso_config,
5582 				  struct nlattr **tb,
5583 				  uint8_t vdev_id)
5584 {
5585 	int rem, i;
5586 	uint32_t count;
5587 	uint8_t j = 0;
5588 	struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
5589 	struct nlattr *curr_attr = NULL;
5590 	struct qdf_mac_addr *deny_list_bssid;
5591 	mac_handle_t mac_handle;
5592 
5593 	/* Parse and fetch number of denylist BSSID */
5594 	if (!tb[PARAMS_NUM_BSSID]) {
5595 		hdd_err("attr num of denylist bssid failed");
5596 		goto fail;
5597 	}
5598 	count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
5599 	if (count > MAX_BSSID_AVOID_LIST) {
5600 		hdd_err("Denylist BSSID count %u exceeds max %u",
5601 			count, MAX_BSSID_AVOID_LIST);
5602 		goto fail;
5603 	}
5604 	hdd_debug("Num of denylist BSSID (%d)", count);
5605 	deny_list_bssid = qdf_mem_malloc(sizeof(*deny_list_bssid) *
5606 					  MAX_BSSID_AVOID_LIST);
5607 	if (!deny_list_bssid)
5608 		goto fail;
5609 
5610 	i = 0;
5611 	if (count && tb[PARAM_BSSID_PARAMS]) {
5612 		nla_for_each_nested(curr_attr,
5613 			tb[PARAM_BSSID_PARAMS],
5614 			rem) {
5615 			if (i == count) {
5616 				hdd_warn("Ignoring excess Denylist BSSID");
5617 				break;
5618 			}
5619 
5620 			if (wlan_cfg80211_nla_parse(tb2,
5621 					 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
5622 					 nla_data(curr_attr),
5623 					 nla_len(curr_attr),
5624 					 wlan_hdd_set_roam_param_policy)) {
5625 				hdd_err("nla_parse failed");
5626 				qdf_mem_free(deny_list_bssid);
5627 				goto fail;
5628 			}
5629 			/* Parse and fetch MAC address */
5630 			if (!tb2[PARAM_SET_BSSID]) {
5631 				hdd_err("attr denylist addr failed");
5632 				qdf_mem_free(deny_list_bssid);
5633 				goto fail;
5634 			}
5635 			if (tb2[PARAM_SET_BSSID_HINT]) {
5636 				struct reject_ap_info ap_info;
5637 
5638 				qdf_mem_zero(&ap_info,
5639 					     sizeof(struct reject_ap_info));
5640 				nla_memcpy(ap_info.bssid.bytes,
5641 					   tb2[PARAM_SET_BSSID],
5642 					   QDF_MAC_ADDR_SIZE);
5643 				ap_info.reject_ap_type = USERSPACE_AVOID_TYPE;
5644 				ap_info.reject_reason =
5645 						REASON_USERSPACE_AVOID_LIST;
5646 				ap_info.source = ADDED_BY_DRIVER;
5647 
5648 				/* This BSSID is avoided and not denylisted */
5649 				ucfg_dlm_add_bssid_to_reject_list(hdd_ctx->pdev,
5650 								  &ap_info);
5651 				i++;
5652 				continue;
5653 			}
5654 			nla_memcpy(deny_list_bssid[j].bytes,
5655 				   tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
5656 			hdd_debug(QDF_MAC_ADDR_FMT,
5657 				  QDF_MAC_ADDR_REF(deny_list_bssid[j].bytes));
5658 			i++;
5659 			j++;
5660 		}
5661 	}
5662 
5663 	if (i < count)
5664 		hdd_warn("Num Denylist BSSID %u less than expected %u",
5665 			 i, count);
5666 
5667 	/* Send the denylist to the denylist mgr component */
5668 	ucfg_dlm_add_userspace_deny_list(hdd_ctx->pdev, deny_list_bssid, j);
5669 	qdf_mem_free(deny_list_bssid);
5670 	mac_handle = hdd_ctx->mac_handle;
5671 	sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
5672 			       REASON_ROAM_SET_DENYLIST_BSSID);
5673 
5674 	return 0;
5675 fail:
5676 	return -EINVAL;
5677 }
5678 
5679 static const struct nla_policy
5680 roam_scan_freq_list_scheme_policy[PARAM_FREQ_LIST_SCHEME_MAX + 1] = {
5681 	[PARAM_SCAN_FREQ_LIST_TYPE] = {.type = NLA_U32},
5682 	[PARAM_SCAN_FREQ_LIST] = {.type = NLA_NESTED},
5683 };
5684 
5685 /**
5686  * hdd_send_roam_scan_channel_freq_list_to_sme() - Send control roam scan freqs
5687  * @hdd_ctx: HDD context
5688  * @vdev_id: vdev id
5689  * @tb: Nested attribute carrying frequency list scheme
5690  *
5691  * Extracts the frequency list and frequency list type from the frequency
5692  * list scheme and send the frequencies to SME.
5693  *
5694  * Return: QDF_STATUS
5695  */
5696 static QDF_STATUS
5697 hdd_send_roam_scan_channel_freq_list_to_sme(struct hdd_context *hdd_ctx,
5698 					    uint8_t vdev_id, struct nlattr *tb)
5699 {
5700 	QDF_STATUS status;
5701 	struct nlattr *tb2[PARAM_FREQ_LIST_SCHEME_MAX + 1], *curr_attr;
5702 	uint8_t num_chan = 0;
5703 	uint32_t freq_list[SIR_MAX_SUPPORTED_CHANNEL_LIST] = {0};
5704 	uint32_t list_type;
5705 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
5706 	int rem;
5707 
5708 	if (wlan_cfg80211_nla_parse_nested(tb2, PARAM_FREQ_LIST_SCHEME_MAX,
5709 					   tb,
5710 					   roam_scan_freq_list_scheme_policy)) {
5711 		hdd_err("nla_parse failed");
5712 		return QDF_STATUS_E_INVAL;
5713 	}
5714 
5715 	if (!tb2[PARAM_SCAN_FREQ_LIST] || !tb2[PARAM_SCAN_FREQ_LIST_TYPE]) {
5716 		hdd_err("ROAM_CONTROL_SCAN_FREQ_LIST or type are not present");
5717 		return QDF_STATUS_E_INVAL;
5718 	}
5719 
5720 	list_type = nla_get_u32(tb2[PARAM_SCAN_FREQ_LIST_TYPE]);
5721 	if (list_type != QCA_PREFERRED_SCAN_FREQ_LIST &&
5722 	    list_type != QCA_SPECIFIC_SCAN_FREQ_LIST) {
5723 		hdd_err("Invalid freq list type received: %u", list_type);
5724 		return QDF_STATUS_E_INVAL;
5725 	}
5726 
5727 	nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
5728 		if (num_chan >= SIR_MAX_SUPPORTED_CHANNEL_LIST) {
5729 			hdd_err("number of channels (%d) supported exceeded max (%d)",
5730 				num_chan, SIR_MAX_SUPPORTED_CHANNEL_LIST);
5731 			return QDF_STATUS_E_INVAL;
5732 		}
5733 		num_chan++;
5734 	}
5735 	num_chan = 0;
5736 
5737 	nla_for_each_nested(curr_attr, tb2[PARAM_SCAN_FREQ_LIST], rem) {
5738 		if (nla_len(curr_attr) != sizeof(uint32_t)) {
5739 			hdd_err("len is not correct for frequency %d",
5740 				num_chan);
5741 			return QDF_STATUS_E_INVAL;
5742 		}
5743 		freq_list[num_chan++] = nla_get_u32(curr_attr);
5744 	}
5745 
5746 	status = sme_update_roam_scan_freq_list(mac_handle, vdev_id, freq_list,
5747 						num_chan, list_type);
5748 	if (QDF_IS_STATUS_ERROR(status))
5749 		hdd_err("Failed to update channel list information");
5750 
5751 	return status;
5752 }
5753 
5754 static const struct nla_policy
5755 roam_control_policy[QCA_ATTR_ROAM_CONTROL_MAX + 1] = {
5756 	[QCA_ATTR_ROAM_CONTROL_ENABLE] = {.type = NLA_U8},
5757 	[QCA_ATTR_ROAM_CONTROL_STATUS] = {.type = NLA_U8},
5758 	[PARAM_FREQ_LIST_SCHEME] = {.type = NLA_NESTED},
5759 	[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD] = {.type = NLA_U32},
5760 	[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL] = {.type = NLA_FLAG},
5761 	[QCA_ATTR_ROAM_CONTROL_TRIGGERS] = {.type = NLA_U32},
5762 	[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA] = {.type = NLA_NESTED},
5763 	[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD] = {.type = NLA_U32},
5764 	[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME] = {.type = NLA_U32},
5765 	[QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD] = {.type = NLA_U32},
5766 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD] = {.type = NLA_U32},
5767 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ] = {
5768 			.type = NLA_U32},
5769 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ] = {
5770 			.type = NLA_U32},
5771 	[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ] = {
5772 			.type = NLA_U32},
5773 	[QCA_ATTR_ROAM_CONTROL_USER_REASON] = {.type = NLA_U32},
5774 	[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS] = {.type = NLA_U32},
5775 	[QCA_ATTR_ROAM_CONTROL_BAND_MASK] = {.type = NLA_U32},
5776 	[QCA_ATTR_ROAM_CONTROL_RX_LINKSPEED_THRESHOLD] = {.type = NLA_U16},
5777 	[QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX] = {.type = NLA_U16},
5778 	[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_NO_REUSE_PARTIAL_SCAN_FREQ] = {
5779 			.type = NLA_U8},
5780 	[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_6GHZ_ONLY_ON_PRIOR_DISCOVERY] = {
5781 			.type = NLA_U8},
5782 	[QCA_ATTR_ROAM_CONTROL_CONNECTED_HIGH_RSSI_OFFSET] = {.type = NLA_U8},
5783 };
5784 
5785 /**
5786  * hdd_send_roam_full_scan_period_to_sme() - Send full roam scan period to SME
5787  * @hdd_ctx: HDD context
5788  * @vdev_id: vdev id
5789  * @full_roam_scan_period: Idle period in seconds between two successive
5790  *			   full channel roam scans
5791  * @check_and_update: If this is true/set, update the value only if the current
5792  *		      configured value is not same as global value read from
5793  *		      ini param. This is to give priority to the user configured
5794  *		      values and retain the value, if updated already.
5795  *		      If this is not set, update the value without any check.
5796  *
5797  * Validate the full roam scan period and send it to firmware
5798  *
5799  * Return: QDF_STATUS
5800  */
5801 static QDF_STATUS
5802 hdd_send_roam_full_scan_period_to_sme(struct hdd_context *hdd_ctx,
5803 				      uint8_t vdev_id,
5804 				      uint32_t full_roam_scan_period,
5805 				      bool check_and_update)
5806 {
5807 	QDF_STATUS status;
5808 	uint32_t full_roam_scan_period_current, full_roam_scan_period_global;
5809 
5810 	if (!ucfg_mlme_validate_full_roam_scan_period(full_roam_scan_period))
5811 		return QDF_STATUS_E_INVAL;
5812 
5813 	hdd_debug("Received Command to Set full roam scan period = %u",
5814 		  full_roam_scan_period);
5815 
5816 	status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
5817 					       &full_roam_scan_period_current);
5818 	if (QDF_IS_STATUS_ERROR(status))
5819 		return status;
5820 
5821 	full_roam_scan_period_global =
5822 		sme_get_full_roam_scan_period_global(hdd_ctx->mac_handle);
5823 	if (check_and_update &&
5824 	    full_roam_scan_period_current != full_roam_scan_period_global) {
5825 		hdd_debug("Full roam scan period is already updated, value: %u",
5826 			  full_roam_scan_period_current);
5827 		return QDF_STATUS_SUCCESS;
5828 	}
5829 	status = sme_update_full_roam_scan_period(hdd_ctx->mac_handle, vdev_id,
5830 						  full_roam_scan_period);
5831 	if (QDF_IS_STATUS_ERROR(status))
5832 		hdd_err("Failed to set full scan period");
5833 
5834 	return status;
5835 }
5836 
5837 /**
5838  * wlan_hdd_convert_control_roam_trigger_bitmap  - Convert the
5839  * vendor specific reason code to internal reason code.
5840  * @trigger_reason_bitmap: Vendor specific roam trigger bitmap
5841  *
5842  * Return: Internal roam trigger bitmap
5843  */
5844 static uint32_t
5845 wlan_hdd_convert_control_roam_trigger_bitmap(uint32_t trigger_reason_bitmap)
5846 {
5847 	uint32_t drv_trigger_bitmap = 0, all_bitmap;
5848 
5849 	/* Enable the complete trigger bitmap when all bits are set in
5850 	 * the control config bitmap
5851 	 */
5852 	all_bitmap = (QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN << 1) - 1;
5853 	if (trigger_reason_bitmap == all_bitmap)
5854 		return BIT(ROAM_TRIGGER_REASON_MAX) - 1;
5855 
5856 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PER)
5857 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PER);
5858 
5859 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BEACON_MISS)
5860 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BMISS);
5861 
5862 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_POOR_RSSI)
5863 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_LOW_RSSI);
5864 
5865 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BETTER_RSSI)
5866 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_HIGH_RSSI);
5867 
5868 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PERIODIC)
5869 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_PERIODIC);
5870 
5871 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DENSE)
5872 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_DENSE);
5873 
5874 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BTM)
5875 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BTM);
5876 
5877 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
5878 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BSS_LOAD);
5879 
5880 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_USER_TRIGGER)
5881 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_FORCED);
5882 
5883 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DEAUTH)
5884 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_DEAUTH);
5885 
5886 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_IDLE)
5887 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_IDLE);
5888 
5889 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_TX_FAILURES)
5890 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_STA_KICKOUT);
5891 
5892 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN)
5893 		drv_trigger_bitmap |= BIT(ROAM_TRIGGER_REASON_BACKGROUND);
5894 
5895 	return drv_trigger_bitmap;
5896 }
5897 
5898 /**
5899  * wlan_hdd_convert_control_roam_scan_scheme_bitmap()  - Convert the
5900  * vendor specific roam scan scheme for roam triggers to internal roam trigger
5901  * bitmap for partial scan.
5902  * @trigger_reason_bitmap: Vendor specific roam trigger bitmap
5903  *
5904  * Return: Internal roam scan scheme bitmap
5905  */
5906 static uint32_t
5907 wlan_hdd_convert_control_roam_scan_scheme_bitmap(uint32_t trigger_reason_bitmap)
5908 {
5909 	uint32_t drv_scan_scheme_bitmap = 0;
5910 
5911 	/*
5912 	 * Partial scan scheme override over default scan scheme only for
5913 	 * the PER, BMISS, Low RSSI, BTM, BSS_LOAD Triggers
5914 	 */
5915 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_PER)
5916 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_PER);
5917 
5918 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BEACON_MISS)
5919 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BMISS);
5920 
5921 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_POOR_RSSI)
5922 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_LOW_RSSI);
5923 
5924 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BTM)
5925 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BTM);
5926 
5927 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_BSS_LOAD)
5928 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BSS_LOAD);
5929 
5930 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_USER_TRIGGER)
5931 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_FORCED);
5932 
5933 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_DEAUTH)
5934 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_DEAUTH);
5935 
5936 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_IDLE)
5937 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_IDLE);
5938 
5939 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_TX_FAILURES)
5940 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_STA_KICKOUT);
5941 
5942 	if (trigger_reason_bitmap & QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN)
5943 		drv_scan_scheme_bitmap |= BIT(ROAM_TRIGGER_REASON_BACKGROUND);
5944 
5945 	return drv_scan_scheme_bitmap;
5946 }
5947 
5948 /**
5949  * hdd_send_roam_triggers_to_sme() - Send roam trigger bitmap to SME
5950  * @hdd_ctx: HDD context
5951  * @vdev_id: vdev id
5952  * @roam_trigger_bitmap: Vendor configured roam trigger bitmap to be configured
5953  *			 to firmware
5954  *
5955  * Send the roam trigger bitmap received to SME
5956  *
5957  * Return: QDF_STATUS
5958  */
5959 static QDF_STATUS
5960 hdd_send_roam_triggers_to_sme(struct hdd_context *hdd_ctx,
5961 			      uint8_t vdev_id,
5962 			      uint32_t roam_trigger_bitmap)
5963 {
5964 	QDF_STATUS status;
5965 	struct wlan_roam_triggers triggers;
5966 	struct wlan_hdd_link_info *link_info;
5967 
5968 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
5969 	if (!link_info) {
5970 		hdd_err("Invalid vdev");
5971 		return QDF_STATUS_E_FAILURE;
5972 	}
5973 
5974 	if (link_info->adapter->device_mode != QDF_STA_MODE) {
5975 		hdd_err("Roam trigger bitmap supported only in STA mode");
5976 		return QDF_STATUS_E_FAILURE;
5977 	}
5978 
5979 	triggers.vdev_id = vdev_id;
5980 	triggers.trigger_bitmap =
5981 	    wlan_hdd_convert_control_roam_trigger_bitmap(roam_trigger_bitmap);
5982 	hdd_debug("trigger bitmap: 0x%x converted trigger_bitmap: 0x%x",
5983 		  roam_trigger_bitmap, triggers.trigger_bitmap);
5984 	/*
5985 	 * In standalone STA, if this vendor command is received between
5986 	 * ROAM_START and roam synch indication, it is better to reject
5987 	 * roam disable since driver would send vdev_params command to
5988 	 * de-initialize roaming structures in fw.
5989 	 * In STA+STA mode, if this vendor command to enable roaming is
5990 	 * received for one STA vdev and ROAM_START was received for other
5991 	 * STA vdev, then also driver would be send vdev_params command to
5992 	 * de-initialize roaming structures in fw on the roaming enabled
5993 	 * vdev.
5994 	 */
5995 	if (hdd_is_roaming_in_progress(hdd_ctx)) {
5996 		mlme_set_roam_trigger_bitmap(hdd_ctx->psoc,
5997 					     link_info->vdev_id,
5998 					     triggers.trigger_bitmap);
5999 		hdd_err("Reject set roam trigger as roaming is in progress");
6000 
6001 		return QDF_STATUS_E_BUSY;
6002 	}
6003 
6004 	/*
6005 	 * roam trigger bitmap is > 0 - Roam triggers are set.
6006 	 * roam trigger bitmap is 0 - Disable roaming
6007 	 *
6008 	 * For both the above modes, reset the roam scan scheme bitmap to
6009 	 * 0.
6010 	 */
6011 	status = ucfg_cm_update_roam_scan_scheme_bitmap(hdd_ctx->psoc,
6012 							vdev_id, 0);
6013 
6014 	status = ucfg_cm_rso_set_roam_trigger(hdd_ctx->pdev, vdev_id,
6015 					      &triggers);
6016 	if (QDF_IS_STATUS_ERROR(status))
6017 		hdd_err("Failed to set roam control trigger bitmap");
6018 
6019 	return status;
6020 }
6021 
6022 /*
6023  * Disable default scoring algorithm. This is intended to set all bits of the
6024  * disable_bitmap in struct scoring_param.
6025  */
6026 #define DISABLE_SCORING 0
6027 
6028 /*
6029  * Enable scoring algorithm. This is intended to clear all bits of the
6030  * disable_bitmap in struct scoring_param.
6031  */
6032 #define ENABLE_SCORING 1
6033 
6034 /*
6035  * Controlled roam candidate selection is enabled from userspace.
6036  * Driver/firmware should honor the selection criteria
6037  */
6038 #define CONTROL_ROAM_CAND_SEL_ENABLE 1
6039 
6040 /*
6041  * Controlled roam candidate selection is disabled from userspace.
6042  * Driver/firmware can use its internal candidate selection criteria
6043  */
6044 #define CONTROL_ROAM_CAND_SEL_DISABLE 0
6045 
6046 static const struct nla_policy
6047 roam_scan_cand_sel_policy[PARAM_CAND_SEL_CRITERIA_MAX + 1] = {
6048 	[PARAM_CAND_SEL_SCORE_RSSI] = {.type = NLA_U8},
6049 };
6050 
6051 /**
6052  * hdd_send_roam_cand_sel_criteria_to_sme() - Send candidate sel criteria to SME
6053  * @hdd_ctx: HDD context
6054  * @vdev_id: vdev id
6055  * @attr: Nested attribute carrying candidate selection criteria
6056  *
6057  * Extract different candidate sel criteria mentioned and convert it to
6058  * driver/firmware understable format.
6059  *
6060  * Return: QDF_STATUS
6061  */
6062 static QDF_STATUS
6063 hdd_send_roam_cand_sel_criteria_to_sme(struct hdd_context *hdd_ctx,
6064 				       uint8_t vdev_id,
6065 				       struct nlattr *attr)
6066 {
6067 	QDF_STATUS status;
6068 	struct nlattr *tb2[PARAM_CAND_SEL_CRITERIA_MAX + 1];
6069 	struct nlattr *curr_attr;
6070 	uint8_t sel_criteria = 0, rssi_score = 0, scoring;
6071 	int rem;
6072 
6073 	hdd_debug("Received Command to Set candidate selection criteria ");
6074 	nla_for_each_nested(curr_attr, attr, rem) {
6075 		sel_criteria++;
6076 		break;
6077 	}
6078 
6079 	if (sel_criteria &&
6080 	    wlan_cfg80211_nla_parse_nested(tb2, PARAM_CAND_SEL_CRITERIA_MAX,
6081 					   attr, roam_scan_cand_sel_policy)) {
6082 		hdd_err("nla_parse failed");
6083 		return QDF_STATUS_E_INVAL;
6084 	}
6085 
6086 	/*
6087 	 * Firmware supports the below configurations currently,
6088 	 * 1. Default selection criteria where all scoring params
6089 	 *    are enabled and different weightages/scores are given to
6090 	 *    different parameters.
6091 	 *    When userspace doesn't specify any candidate selection criteria,
6092 	 *    this will be enabled.
6093 	 * 2. Legacy candidate selection criteria where scoring
6094 	 *    algorithm is disabled and only RSSI is considered for
6095 	 *    roam candidate selection.
6096 	 *    When userspace specify 100% weightage for RSSI, this will
6097 	 *    be enabled.
6098 	 * Rest of the combinations are not supported for now.
6099 	 */
6100 	if (sel_criteria == CONTROL_ROAM_CAND_SEL_ENABLE) {
6101 		/* Legacy selection criteria: 100% weightage to RSSI */
6102 		if (tb2[PARAM_CAND_SEL_SCORE_RSSI])
6103 			rssi_score = nla_get_u8(tb2[PARAM_CAND_SEL_SCORE_RSSI]);
6104 
6105 		if (rssi_score != 100) {
6106 			hdd_debug("Ignore the candidate selection criteria");
6107 			return QDF_STATUS_E_INVAL;
6108 		}
6109 		scoring = DISABLE_SCORING;
6110 	} else {
6111 		/* Default selection criteria */
6112 		scoring = ENABLE_SCORING;
6113 	}
6114 
6115 	status = sme_modify_roam_cand_sel_criteria(hdd_ctx->mac_handle, vdev_id,
6116 						   !!scoring);
6117 	if (QDF_IS_STATUS_ERROR(status))
6118 		hdd_err("Failed to disable scoring");
6119 
6120 	return status;
6121 }
6122 
6123 /**
6124  * hdd_send_roam_scan_period_to_sme() - Send roam scan period to SME
6125  * @hdd_ctx: HDD context
6126  * @vdev_id: vdev id
6127  * @roam_scan_period: Roam scan period in seconds
6128  * @check_and_update: If this is true/set, update the value only if the current
6129  *		      configured value is not same as global value read from
6130  *		      ini param. This is to give priority to the user configured
6131  *		      values and retain the value, if updated already.
6132  *		      If this is not set, update the value without any check.
6133  *
6134  * Validate the roam scan period and send it to firmware if valid.
6135  *
6136  * Return: QDF_STATUS
6137  */
6138 static QDF_STATUS
6139 hdd_send_roam_scan_period_to_sme(struct hdd_context *hdd_ctx,
6140 				 uint8_t vdev_id,
6141 				 uint32_t roam_scan_period,
6142 				 bool check_and_update)
6143 {
6144 	QDF_STATUS status;
6145 	uint16_t roam_scan_period_current, roam_scan_period_global = 0;
6146 
6147 	if (!ucfg_mlme_validate_scan_period(hdd_ctx->psoc,
6148 					    roam_scan_period * 1000))
6149 		return QDF_STATUS_E_INVAL;
6150 
6151 	hdd_debug("Received Command to Set roam scan period (Empty Scan refresh period) = %d",
6152 		  roam_scan_period);
6153 
6154 	status = ucfg_cm_get_empty_scan_refresh_period(
6155 						hdd_ctx->psoc, vdev_id,
6156 						&roam_scan_period_current);
6157 	if (QDF_IS_STATUS_ERROR(status))
6158 		return status;
6159 
6160 	ucfg_cm_get_empty_scan_refresh_period_global(hdd_ctx->psoc,
6161 						     &roam_scan_period_global);
6162 	if (check_and_update &&
6163 	    roam_scan_period_current != roam_scan_period_global) {
6164 		hdd_debug("roam scan period is already updated, value: %u",
6165 			  roam_scan_period_current / 1000);
6166 		return QDF_STATUS_SUCCESS;
6167 	}
6168 	status = sme_update_empty_scan_refresh_period(hdd_ctx->mac_handle,
6169 						      vdev_id,
6170 						      roam_scan_period * 1000);
6171 	if (QDF_IS_STATUS_ERROR(status))
6172 		hdd_err("Failed to set scan period");
6173 
6174 	return status;
6175 }
6176 
6177 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && \
6178 defined(FEATURE_RX_LINKSPEED_ROAM_TRIGGER)
6179 /**
6180  * hdd_set_roam_rx_linkspeed_threshold() - Set rx link speed threshold
6181  * @psoc: Pointer to psoc
6182  * @vdev: vdev
6183  * @linkspeed_threshold: threshold value to set
6184  *
6185  * Return: none
6186  */
6187 static QDF_STATUS
6188 hdd_set_roam_rx_linkspeed_threshold(struct wlan_objmgr_psoc *psoc,
6189 				    struct wlan_objmgr_vdev *vdev,
6190 				    uint32_t linkspeed_threshold)
6191 {
6192 	if (!ucfg_cm_is_linkspeed_roam_trigger_supported(psoc))
6193 		return QDF_STATUS_E_NOSUPPORT;
6194 
6195 	if (linkspeed_threshold) {
6196 		dp_ucfg_enable_link_monitoring(psoc, vdev,
6197 					       linkspeed_threshold);
6198 	} else {
6199 		dp_ucfg_disable_link_monitoring(psoc, vdev);
6200 		wlan_hdd_link_speed_update(psoc, wlan_vdev_get_id(vdev),
6201 					   false);
6202 	}
6203 
6204 	return QDF_STATUS_SUCCESS;
6205 }
6206 #else
6207 static inline QDF_STATUS
6208 hdd_set_roam_rx_linkspeed_threshold(struct wlan_objmgr_psoc *psoc,
6209 				    struct wlan_objmgr_vdev *vdev,
6210 				    uint32_t linkspeed_threshold)
6211 {
6212 	return QDF_STATUS_E_NOSUPPORT;
6213 }
6214 #endif
6215 
6216 /* Roam Hand-off delay range is 20 to 1000 msec */
6217 #define MIN_ROAM_HO_DELAY 20
6218 #define MAX_ROAM_HO_DELAY 1000
6219 
6220 /* Include/Exclude roam partial scan channels in full scan */
6221 #define INCLUDE_ROAM_PARTIAL_SCAN_FREQ 0
6222 #define EXCLUDE_ROAM_PARTIAL_SCAN_FREQ 1
6223 
6224 /* Include the supported 6 GHz PSC channels in full scan by default */
6225 #define INCLUDE_6GHZ_IN_FULL_SCAN_BY_DEF	0
6226 /* Include the 6 GHz channels in roam full scan only on prior discovery */
6227 #define INCLUDE_6GHZ_IN_FULL_SCAN_IF_DISC	1
6228 
6229 #ifdef WLAN_VENDOR_HANDOFF_CONTROL
6230 /**
6231  * hdd_get_handoff_param() - get vendor handoff parameters
6232  * @hdd_ctx: HDD context
6233  * @vdev_id: vdev id
6234  *
6235  * Wrapper function for hdd_cm_get_handoff_param
6236  *
6237  * Return: QDF_STATUS
6238  */
6239 static QDF_STATUS hdd_get_handoff_param(struct hdd_context *hdd_ctx,
6240 					uint8_t vdev_id)
6241 {
6242 	return hdd_cm_get_handoff_param(hdd_ctx->psoc, vdev_id,
6243 					VENDOR_CONTROL_PARAM_ROAM_ALL);
6244 }
6245 #else
6246 static inline QDF_STATUS
6247 hdd_get_handoff_param(struct hdd_context *hdd_ctx, uint8_t vdev_id)
6248 {
6249 	return QDF_STATUS_SUCCESS;
6250 }
6251 #endif
6252 
6253 /**
6254  * hdd_set_roam_with_control_config() - Set roam control configuration
6255  * @hdd_ctx: HDD context
6256  * @tb: List of attributes carrying roam subcmd data
6257  * @vdev_id: vdev id
6258  *
6259  * Extracts the attribute PARAM_ROAM_CONTROL_CONFIG from the attributes list tb
6260  * and sends the corresponding roam control configuration to driver/firmware.
6261  *
6262  * Return: 0 on success; error number on failure
6263  */
6264 static int
6265 hdd_set_roam_with_control_config(struct hdd_context *hdd_ctx,
6266 				 struct nlattr **tb,
6267 				 uint8_t vdev_id)
6268 {
6269 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6270 	struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1], *attr;
6271 	uint32_t value;
6272 	struct wlan_cm_roam_vendor_btm_params param = {0};
6273 	bool is_wtc_param_updated = false;
6274 	uint32_t band_mask;
6275 	uint16_t threshold;
6276 	struct wlan_hdd_link_info *link_info;
6277 	uint8_t roam_control_enable = false;
6278 
6279 	hdd_enter();
6280 
6281 	/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
6282 	if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
6283 		hdd_err("Attribute CONTROL_CONFIG is not present");
6284 		return -EINVAL;
6285 	}
6286 
6287 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6288 	if (!link_info || hdd_validate_adapter(link_info->adapter))
6289 		return QDF_STATUS_E_FAILURE;
6290 
6291 	if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
6292 					   tb[PARAM_ROAM_CONTROL_CONFIG],
6293 					   roam_control_policy)) {
6294 		hdd_err("nla_parse failed");
6295 		return -EINVAL;
6296 	}
6297 
6298 	attr = tb2[PARAM_FREQ_LIST_SCHEME];
6299 	if (attr) {
6300 		status = hdd_send_roam_scan_channel_freq_list_to_sme(hdd_ctx,
6301 								     vdev_id,
6302 								     attr);
6303 		if (QDF_IS_STATUS_ERROR(status))
6304 			hdd_err("failed to config roam control");
6305 	}
6306 
6307 	if (tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]) {
6308 		value = nla_get_u32(tb2[QCA_ATTR_ROAM_CONTROL_TRIGGERS]);
6309 		hdd_debug("Received roam trigger bitmap: 0x%x", value);
6310 		status = hdd_send_roam_triggers_to_sme(hdd_ctx,
6311 						       vdev_id,
6312 						       value);
6313 		if (status)
6314 			hdd_err("failed to config roam triggers");
6315 	}
6316 
6317 	attr = tb2[QCA_ATTR_ROAM_CONTROL_ENABLE];
6318 	if (attr) {
6319 		roam_control_enable = nla_get_u8(attr);
6320 		if (roam_control_enable &&
6321 		    ucfg_cm_roam_is_vendor_handoff_control_enable(
6322 			hdd_ctx->psoc)) {
6323 			status = hdd_get_handoff_param(hdd_ctx, vdev_id);
6324 			if (QDF_IS_STATUS_ERROR(status)) {
6325 				hdd_err("failed to get vendor handoff params");
6326 				return qdf_status_to_os_return(status);
6327 			}
6328 		}
6329 
6330 		hdd_debug("Parse and send roam control to FW: %s",
6331 			  roam_control_enable ? "Enable" : "Disable");
6332 
6333 		status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
6334 						    vdev_id,
6335 						    roam_control_enable);
6336 		if (QDF_IS_STATUS_ERROR(status))
6337 			hdd_err("failed to enable/disable roam control config");
6338 
6339 		attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
6340 		if (attr) {
6341 			/* Default value received as part of Roam control enable
6342 			 * Set this only if user hasn't configured any value so
6343 			 * far.
6344 			 */
6345 			value = nla_get_u32(attr);
6346 			status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
6347 								  vdev_id,
6348 								  value, true);
6349 			if (QDF_IS_STATUS_ERROR(status))
6350 				hdd_err("failed to send scan period to firmware");
6351 		}
6352 
6353 		attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
6354 		if (attr) {
6355 			value = nla_get_u32(attr);
6356 			/* Default value received as part of Roam control enable
6357 			 * Set this only if user hasn't configured any value so
6358 			 * far.
6359 			 */
6360 			status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
6361 								       vdev_id,
6362 								       value,
6363 								       true);
6364 			if (status)
6365 				hdd_err("failed to config full scan period");
6366 		}
6367 	} else {
6368 		attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD];
6369 		if (attr) {
6370 			/* User configured value, cache the value directly */
6371 			value = nla_get_u32(attr);
6372 			status = hdd_send_roam_scan_period_to_sme(hdd_ctx,
6373 								  vdev_id,
6374 								  value, false);
6375 			if (QDF_IS_STATUS_ERROR(status))
6376 				hdd_err("failed to send scan period to firmware");
6377 		}
6378 
6379 		attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD];
6380 		if (attr) {
6381 			value = nla_get_u32(attr);
6382 			/* User configured value, cache the value directly */
6383 			status = hdd_send_roam_full_scan_period_to_sme(hdd_ctx,
6384 								       vdev_id,
6385 								       value,
6386 								       false);
6387 			if (status)
6388 				hdd_err("failed to config full scan period");
6389 		}
6390 	}
6391 
6392 	attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS];
6393 	if (attr) {
6394 		value = wlan_hdd_convert_control_roam_scan_scheme_bitmap(
6395 							nla_get_u32(attr));
6396 		status = ucfg_cm_update_roam_scan_scheme_bitmap(hdd_ctx->psoc,
6397 								vdev_id,
6398 								value);
6399 	}
6400 
6401 	/* Scoring and roam candidate selection criteria */
6402 	attr = tb2[QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA];
6403 	if (attr) {
6404 		status = hdd_send_roam_cand_sel_criteria_to_sme(hdd_ctx,
6405 								vdev_id, attr);
6406 		if (QDF_IS_STATUS_ERROR(status))
6407 			hdd_err("failed to set candidate selection criteria");
6408 	}
6409 
6410 	attr = tb2[QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME];
6411 	if (attr) {
6412 		param.scan_freq_scheme = nla_get_u32(attr);
6413 		is_wtc_param_updated = true;
6414 	}
6415 
6416 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD];
6417 	if (attr) {
6418 		param.connected_rssi_threshold = nla_get_u32(attr);
6419 		is_wtc_param_updated = true;
6420 	}
6421 
6422 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD];
6423 	if (attr) {
6424 		param.candidate_rssi_threshold_2g = nla_get_u32(attr);
6425 		is_wtc_param_updated = true;
6426 	}
6427 
6428 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ];
6429 	if (attr) {
6430 		param.candidate_rssi_threshold_2g = nla_get_u32(attr);
6431 		is_wtc_param_updated = true;
6432 	}
6433 
6434 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ];
6435 	if (attr) {
6436 		param.candidate_rssi_threshold_5g = nla_get_u32(attr);
6437 		is_wtc_param_updated = true;
6438 	} else {
6439 		param.candidate_rssi_threshold_5g =
6440 					param.candidate_rssi_threshold_2g;
6441 	}
6442 
6443 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ];
6444 	if (attr) {
6445 		param.candidate_rssi_threshold_6g = nla_get_u32(attr);
6446 		is_wtc_param_updated = true;
6447 	} else {
6448 		param.candidate_rssi_threshold_6g =
6449 					param.candidate_rssi_threshold_2g;
6450 	}
6451 
6452 	attr = tb2[QCA_ATTR_ROAM_CONTROL_USER_REASON];
6453 	if (attr) {
6454 		param.user_roam_reason = nla_get_u32(attr);
6455 		is_wtc_param_updated = true;
6456 	} else {
6457 		param.user_roam_reason = DISABLE_VENDOR_BTM_CONFIG;
6458 	}
6459 
6460 	if (tb2[QCA_ATTR_ROAM_CONTROL_BAND_MASK]) {
6461 		band_mask =
6462 			nla_get_u32(tb2[QCA_ATTR_ROAM_CONTROL_BAND_MASK]);
6463 		band_mask =
6464 			wlan_vendor_bitmap_to_reg_wifi_band_bitmap(hdd_ctx->psoc,
6465 								   band_mask);
6466 		hdd_debug("[ROAM BAND] set roam band mask:%d", band_mask);
6467 		if (band_mask) {
6468 			ucfg_cm_set_roam_band_mask(hdd_ctx->psoc, vdev_id,
6469 						   band_mask);
6470 		} else {
6471 			hdd_debug("Invalid roam BAND_MASK");
6472 			return -EINVAL;
6473 		}
6474 
6475 		if (ucfg_cm_is_change_in_band_allowed(hdd_ctx->psoc, vdev_id,
6476 						      band_mask)) {
6477 
6478 			/* Disable roaming on Vdev before setting PCL */
6479 			sme_stop_roaming(hdd_ctx->mac_handle, vdev_id,
6480 					 REASON_DRIVER_DISABLED, RSO_SET_PCL);
6481 
6482 			policy_mgr_set_pcl_for_existing_combo(hdd_ctx->psoc,
6483 							      PM_STA_MODE,
6484 							      vdev_id);
6485 
6486 			/* Enable roaming once SET pcl is done */
6487 			sme_start_roaming(hdd_ctx->mac_handle, vdev_id,
6488 					  REASON_DRIVER_ENABLED, RSO_SET_PCL);
6489 		}
6490 	}
6491 
6492 	attr = tb2[QCA_ATTR_ROAM_CONTROL_RX_LINKSPEED_THRESHOLD];
6493 	if (attr) {
6494 		threshold = nla_get_u16(attr);
6495 		status = hdd_set_roam_rx_linkspeed_threshold(hdd_ctx->psoc,
6496 							     link_info->vdev,
6497 							     threshold);
6498 	}
6499 
6500 	if (is_wtc_param_updated) {
6501 		wlan_cm_roam_set_vendor_btm_params(hdd_ctx->psoc, &param);
6502 		/* Sends RSO update */
6503 		sme_send_vendor_btm_params(hdd_ctx->mac_handle, vdev_id);
6504 	}
6505 
6506 	attr = tb2[QCA_ATTR_ROAM_CONTROL_HO_DELAY_FOR_RX];
6507 	if (attr) {
6508 		value = nla_get_u16(attr);
6509 		if (value < MIN_ROAM_HO_DELAY || value > MAX_ROAM_HO_DELAY) {
6510 			hdd_err("Invalid roam HO delay value: %d", value);
6511 			return -EINVAL;
6512 		}
6513 
6514 		hdd_debug("Received roam HO delay value: %d", value);
6515 
6516 		status = ucfg_cm_roam_send_ho_delay_config(hdd_ctx->pdev,
6517 							   vdev_id, value);
6518 		if (QDF_IS_STATUS_ERROR(status))
6519 			hdd_err("failed to set hand-off delay");
6520 	}
6521 
6522 	attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_NO_REUSE_PARTIAL_SCAN_FREQ];
6523 	if (attr) {
6524 		value = nla_get_u8(attr);
6525 		if (value < INCLUDE_ROAM_PARTIAL_SCAN_FREQ ||
6526 		    value > EXCLUDE_ROAM_PARTIAL_SCAN_FREQ) {
6527 			hdd_err("Invalid value %d to exclude partial scan freq",
6528 				value);
6529 			return -EINVAL;
6530 		}
6531 
6532 		hdd_debug("%s partial scan channels in roam full scan",
6533 			  value ? "Exclude" : "Include");
6534 
6535 		status = ucfg_cm_exclude_rm_partial_scan_freq(hdd_ctx->pdev,
6536 							      vdev_id, value);
6537 		if (QDF_IS_STATUS_ERROR(status))
6538 			hdd_err("Fail to exclude roam partial scan channels");
6539 	}
6540 
6541 	attr = tb2[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_6GHZ_ONLY_ON_PRIOR_DISCOVERY];
6542 	if (attr) {
6543 		value = nla_get_u8(attr);
6544 		if (value < INCLUDE_6GHZ_IN_FULL_SCAN_BY_DEF ||
6545 		    value > INCLUDE_6GHZ_IN_FULL_SCAN_IF_DISC) {
6546 			hdd_err("Invalid value %d to decide inclusion of 6 GHz channels",
6547 				value);
6548 			return -EINVAL;
6549 		}
6550 
6551 		hdd_debug("Include 6 GHz channels in roam full scan by %s",
6552 			  value ? "prior discovery" : "default");
6553 
6554 		status = ucfg_cm_roam_full_scan_6ghz_on_disc(hdd_ctx->pdev,
6555 							     vdev_id, value);
6556 		if (QDF_IS_STATUS_ERROR(status))
6557 			hdd_err("Fail to decide inclusion of 6 GHz channels");
6558 	}
6559 
6560 	attr = tb2[QCA_ATTR_ROAM_CONTROL_CONNECTED_HIGH_RSSI_OFFSET];
6561 	if (attr) {
6562 		value = nla_get_u8(attr);
6563 		if (!cfg_in_range(CFG_LFR_ROAM_SCAN_HI_RSSI_DELTA, value)) {
6564 			hdd_err("High RSSI offset value %d is out of range",
6565 				value);
6566 			return -EINVAL;
6567 		}
6568 
6569 		hdd_debug("%s roam scan high RSSI with offset: %d for vdev %d",
6570 			  value ? "Enable" : "Disable", value, vdev_id);
6571 
6572 		if (!value &&
6573 		    !wlan_cm_get_roam_scan_high_rssi_offset(hdd_ctx->psoc)) {
6574 			hdd_debug("Roam scan high RSSI is already disabled");
6575 			return -EINVAL;
6576 		}
6577 
6578 		status = ucfg_cm_set_roam_scan_high_rssi_offset(hdd_ctx->psoc,
6579 								vdev_id, value);
6580 		if (QDF_IS_STATUS_ERROR(status))
6581 			hdd_err("Fail to set roam scan high RSSI offset for vdev %d",
6582 				vdev_id);
6583 	}
6584 
6585 	return qdf_status_to_os_return(status);
6586 }
6587 
6588 #define ENABLE_ROAM_TRIGGERS_ALL (QCA_ROAM_TRIGGER_REASON_PER | \
6589 				  QCA_ROAM_TRIGGER_REASON_BEACON_MISS | \
6590 				  QCA_ROAM_TRIGGER_REASON_POOR_RSSI | \
6591 				  QCA_ROAM_TRIGGER_REASON_BETTER_RSSI | \
6592 				  QCA_ROAM_TRIGGER_REASON_PERIODIC | \
6593 				  QCA_ROAM_TRIGGER_REASON_DENSE | \
6594 				  QCA_ROAM_TRIGGER_REASON_BTM | \
6595 				  QCA_ROAM_TRIGGER_REASON_BSS_LOAD | \
6596 				  QCA_ROAM_TRIGGER_REASON_USER_TRIGGER | \
6597 				  QCA_ROAM_TRIGGER_REASON_DEAUTH | \
6598 				  QCA_ROAM_TRIGGER_REASON_IDLE | \
6599 				  QCA_ROAM_TRIGGER_REASON_TX_FAILURES | \
6600 				  QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN)
6601 
6602 static int
6603 hdd_clear_roam_control_config(struct hdd_context *hdd_ctx,
6604 			      struct nlattr **tb,
6605 			      uint8_t vdev_id)
6606 {
6607 	QDF_STATUS status;
6608 	struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
6609 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
6610 	uint32_t value;
6611 
6612 	/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
6613 	if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
6614 		hdd_err("Attribute CONTROL_CONFIG is not present");
6615 		return -EINVAL;
6616 	}
6617 
6618 	if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
6619 					   tb[PARAM_ROAM_CONTROL_CONFIG],
6620 					   roam_control_policy)) {
6621 		hdd_err("nla_parse failed");
6622 		return -EINVAL;
6623 	}
6624 
6625 	hdd_debug("Clear the control config done through SET");
6626 	if (tb2[QCA_ATTR_ROAM_CONTROL_CLEAR_ALL]) {
6627 		hdd_debug("Disable roam control config done through SET");
6628 		status = sme_set_roam_config_enable(hdd_ctx->mac_handle,
6629 						    vdev_id, 0);
6630 		if (QDF_IS_STATUS_ERROR(status)) {
6631 			hdd_err("failed to enable/disable roam control config");
6632 			return qdf_status_to_os_return(status);
6633 		}
6634 
6635 		value = ENABLE_ROAM_TRIGGERS_ALL;
6636 		hdd_debug("Reset roam trigger bitmap to 0x%x", value);
6637 		status = hdd_send_roam_triggers_to_sme(hdd_ctx, vdev_id, value);
6638 		if (QDF_IS_STATUS_ERROR(status)) {
6639 			hdd_err("failed to restore roam trigger bitmap");
6640 			return qdf_status_to_os_return(status);
6641 		}
6642 
6643 		status = sme_roam_control_restore_default_config(mac_handle,
6644 								 vdev_id);
6645 		if (QDF_IS_STATUS_ERROR(status)) {
6646 			hdd_err("failed to config roam control");
6647 			return qdf_status_to_os_return(status);
6648 		}
6649 	}
6650 
6651 	return 0;
6652 }
6653 
6654 /**
6655  * hdd_roam_control_config_buf_size() - Calculate the skb size to be allocated
6656  * @hdd_ctx: HDD context
6657  * @tb: List of attributes to be populated
6658  *
6659  * Calculate the buffer size to be allocated based on the attributes
6660  * mentioned in tb.
6661  *
6662  * Return: buffer size to be allocated
6663  */
6664 static uint16_t
6665 hdd_roam_control_config_buf_size(struct hdd_context *hdd_ctx,
6666 				 struct nlattr **tb)
6667 {
6668 	uint16_t skb_len = 0;
6669 
6670 	if (tb[QCA_ATTR_ROAM_CONTROL_STATUS])
6671 		skb_len += NLA_HDRLEN + sizeof(uint8_t);
6672 
6673 	if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD])
6674 		skb_len += NLA_HDRLEN + sizeof(uint32_t);
6675 
6676 	if (tb[QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME])
6677 		/*
6678 		 * Response has 3 nests, 1 atrribure value and a
6679 		 * attribute list of frequencies.
6680 		 */
6681 		skb_len += 3 * nla_total_size(0) +
6682 			nla_total_size(sizeof(uint32_t)) +
6683 			(nla_total_size(sizeof(uint32_t)) *
6684 			NUM_CHANNELS);
6685 
6686 	if (tb[QCA_ATTR_ROAM_CONTROL_BAND_MASK])
6687 		skb_len += NLA_HDRLEN + sizeof(uint32_t);
6688 
6689 	return skb_len;
6690 }
6691 
6692 /**
6693  * wlan_reg_wifi_band_bitmap_to_vendor_bitmap() - Convert enum reg_wifi_band
6694  * to enum qca_set_band
6695  * @reg_wifi_band_bitmap: enum reg_wifi_band
6696  *
6697  * Return: qca_set_band value
6698  */
6699 static uint32_t
6700 wlan_reg_wifi_band_bitmap_to_vendor_bitmap(uint32_t reg_wifi_band_bitmap)
6701 {
6702 	uint32_t vendor_mask = 0;
6703 
6704 	if (reg_wifi_band_bitmap & BIT(REG_BAND_2G))
6705 		vendor_mask |= QCA_SETBAND_2G;
6706 	if (reg_wifi_band_bitmap & BIT(REG_BAND_5G))
6707 		vendor_mask |= QCA_SETBAND_5G;
6708 	if (reg_wifi_band_bitmap & BIT(REG_BAND_6G))
6709 		vendor_mask |= QCA_SETBAND_6G;
6710 
6711 	return vendor_mask;
6712 }
6713 
6714 /**
6715  * hdd_roam_control_config_fill_data() - Fill the data requested by userspace
6716  * @hdd_ctx: HDD context
6717  * @vdev_id: vdev id
6718  * @skb: SK buffer
6719  * @tb: List of attributes
6720  *
6721  * Get the data corresponding to the attribute list specified in tb and
6722  * update the same to skb by populating the same attributes.
6723  *
6724  * Return: 0 on success; error number on failure
6725  */
6726 static int
6727 hdd_roam_control_config_fill_data(struct hdd_context *hdd_ctx, uint8_t vdev_id,
6728 				  struct sk_buff *skb, struct nlattr **tb)
6729 {
6730 	QDF_STATUS status = QDF_STATUS_SUCCESS;
6731 	uint8_t roam_control;
6732 	struct nlattr *config, *get_freq_scheme, *get_freq;
6733 	uint32_t full_roam_scan_period, roam_band, vendor_band_mask;
6734 	uint8_t num_channels = 0;
6735 	uint32_t i = 0, freq_list[NUM_CHANNELS] = { 0 };
6736 	struct wlan_hdd_link_info *link_info;
6737 
6738 	config = nla_nest_start(skb, PARAM_ROAM_CONTROL_CONFIG);
6739 	if (!config) {
6740 		hdd_err("nla nest start failure");
6741 		return -EINVAL;
6742 	}
6743 
6744 	if (tb[QCA_ATTR_ROAM_CONTROL_STATUS]) {
6745 		status = sme_get_roam_config_status(hdd_ctx->mac_handle,
6746 						    vdev_id,
6747 						    &roam_control);
6748 		if (QDF_IS_STATUS_ERROR(status))
6749 			goto out;
6750 		hdd_debug("Roam control: %s",
6751 			  roam_control ? "Enabled" : "Disabled");
6752 		if (nla_put_u8(skb, QCA_ATTR_ROAM_CONTROL_STATUS,
6753 			       roam_control)) {
6754 			hdd_info("failed to put vendor_roam_control");
6755 			return -ENOMEM;
6756 		}
6757 	}
6758 
6759 	if (tb[QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD]) {
6760 		status = sme_get_full_roam_scan_period(hdd_ctx->mac_handle,
6761 						       vdev_id,
6762 						       &full_roam_scan_period);
6763 		if (QDF_IS_STATUS_ERROR(status))
6764 			goto out;
6765 		hdd_debug("full_roam_scan_period: %u", full_roam_scan_period);
6766 
6767 		if (nla_put_u32(skb, QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD,
6768 				full_roam_scan_period)) {
6769 			hdd_info("failed to put full_roam_scan_period");
6770 			return -EINVAL;
6771 		}
6772 	}
6773 
6774 	if (tb[QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME]) {
6775 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
6776 		if (!link_info) {
6777 			hdd_info("Invalid vdev");
6778 			return -EINVAL;
6779 		}
6780 
6781 		hdd_debug("Get roam scan frequencies req received");
6782 		status = hdd_get_roam_scan_freq(link_info->adapter,
6783 						hdd_ctx->mac_handle,
6784 						freq_list, &num_channels);
6785 		if (QDF_IS_STATUS_ERROR(status)) {
6786 			hdd_info("failed to get roam scan freq");
6787 			goto out;
6788 		}
6789 
6790 		hdd_debug("num_channels %d", num_channels);
6791 		get_freq_scheme = nla_nest_start(
6792 				skb, QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME);
6793 		if (!get_freq_scheme) {
6794 			hdd_info("failed to nest start for roam scan freq");
6795 			return -EINVAL;
6796 		}
6797 
6798 		if (nla_put_u32(skb, PARAM_SCAN_FREQ_LIST_TYPE, 0)) {
6799 			hdd_info("failed to put list type");
6800 			return -EINVAL;
6801 		}
6802 
6803 		get_freq = nla_nest_start(
6804 				skb, QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST);
6805 		if (!get_freq) {
6806 			hdd_info("failed to nest start for roam scan freq");
6807 			return -EINVAL;
6808 		}
6809 
6810 		for (i = 0; i < num_channels; i++) {
6811 			if (nla_put_u32(skb, PARAM_SCAN_FREQ_LIST,
6812 					freq_list[i])) {
6813 				hdd_info("failed to put freq at index %d", i);
6814 				return -EINVAL;
6815 			}
6816 		}
6817 		nla_nest_end(skb, get_freq);
6818 		nla_nest_end(skb, get_freq_scheme);
6819 	}
6820 
6821 	if (tb[QCA_ATTR_ROAM_CONTROL_BAND_MASK]) {
6822 		status = ucfg_cm_get_roam_band(hdd_ctx->psoc, vdev_id,
6823 					       &roam_band);
6824 		if (QDF_IS_STATUS_ERROR(status))
6825 			goto out;
6826 		vendor_band_mask =
6827 			wlan_reg_wifi_band_bitmap_to_vendor_bitmap(roam_band);
6828 		if (nla_put_u32(skb, QCA_ATTR_ROAM_CONTROL_BAND_MASK,
6829 				vendor_band_mask)) {
6830 			hdd_info("failed to put roam_band");
6831 			return -EINVAL;
6832 		}
6833 		hdd_debug("sending vendor_band_mask: %d reg band:%d",
6834 			  vendor_band_mask, roam_band);
6835 	}
6836 
6837 	nla_nest_end(skb, config);
6838 
6839 out:
6840 	return qdf_status_to_os_return(status);
6841 }
6842 
6843 /**
6844  * hdd_send_roam_control_config() - Send the roam config as vendor cmd reply
6845  * @hdd_ctx: HDD context
6846  * @vdev_id: vdev id
6847  * @tb: List of attributes
6848  *
6849  * Parse the attributes list tb and  get the data corresponding to the
6850  * attributes specified in tb. Send them as a vendor response.
6851  *
6852  * Return: 0 on success; error number on failure
6853  */
6854 static int
6855 hdd_send_roam_control_config(struct hdd_context *hdd_ctx,
6856 			     uint8_t vdev_id,
6857 			     struct nlattr **tb)
6858 {
6859 	struct sk_buff *skb;
6860 	uint16_t skb_len;
6861 	int status;
6862 
6863 	skb_len = hdd_roam_control_config_buf_size(hdd_ctx, tb);
6864 	if (!skb_len) {
6865 		hdd_err("No data requested");
6866 		return -EINVAL;
6867 	}
6868 
6869 	skb_len += NLMSG_HDRLEN;
6870 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
6871 	if (!skb) {
6872 		hdd_info("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
6873 		return -ENOMEM;
6874 	}
6875 
6876 	status = hdd_roam_control_config_fill_data(hdd_ctx, vdev_id, skb, tb);
6877 	if (status)
6878 		goto fail;
6879 
6880 	return wlan_cfg80211_vendor_cmd_reply(skb);
6881 
6882 fail:
6883 	hdd_err("nla put fail");
6884 	wlan_cfg80211_vendor_free_skb(skb);
6885 	return status;
6886 }
6887 
6888 /**
6889  * hdd_get_roam_control_config() - Send requested roam config to userspace
6890  * @hdd_ctx: HDD context
6891  * @tb: list of attributes
6892  * @vdev_id: vdev id
6893  *
6894  * Return: 0 on success; error number on failure
6895  */
6896 static int hdd_get_roam_control_config(struct hdd_context *hdd_ctx,
6897 				       struct nlattr **tb,
6898 				       uint8_t vdev_id)
6899 {
6900 	QDF_STATUS status;
6901 	struct nlattr *tb2[QCA_ATTR_ROAM_CONTROL_MAX + 1];
6902 
6903 	/* The command must carry PARAM_ROAM_CONTROL_CONFIG */
6904 	if (!tb[PARAM_ROAM_CONTROL_CONFIG]) {
6905 		hdd_err("Attribute CONTROL_CONFIG is not present");
6906 		return -EINVAL;
6907 	}
6908 
6909 	if (wlan_cfg80211_nla_parse_nested(tb2, QCA_ATTR_ROAM_CONTROL_MAX,
6910 					   tb[PARAM_ROAM_CONTROL_CONFIG],
6911 					   roam_control_policy)) {
6912 		hdd_err("nla_parse failed");
6913 		return -EINVAL;
6914 	}
6915 
6916 	status = hdd_send_roam_control_config(hdd_ctx, vdev_id, tb2);
6917 	if (status) {
6918 		hdd_err("failed to enable/disable roam control");
6919 		return status;
6920 	}
6921 
6922 	return qdf_status_to_os_return(status);
6923 }
6924 
6925 #undef PARAM_ROAM_CONTROL_CONFIG
6926 #undef PARAM_FREQ_LIST_SCHEME_MAX
6927 #undef PARAM_FREQ_LIST_SCHEME
6928 #undef PARAM_SCAN_FREQ_LIST
6929 #undef PARAM_SCAN_FREQ_LIST_TYPE
6930 #undef PARAM_CAND_SEL_CRITERIA_MAX
6931 #undef PARAM_CAND_SEL_SCORE_RSSI
6932 
6933 /**
6934  * hdd_set_ext_roam_params() - parse ext roam params
6935  * @hdd_ctx: HDD context
6936  * @data: ext roam params attribute payload
6937  * @data_len: length of @data
6938  * @vdev_id: vdev id
6939  * @rso_config: roam params
6940  * @rso_usr_cfg: roam userspace params
6941  *
6942  * Return: 0 on success; error number on failure
6943  */
6944 static int hdd_set_ext_roam_params(struct hdd_context *hdd_ctx,
6945 				   const void *data, int data_len,
6946 				   uint8_t vdev_id,
6947 				   struct rso_config_params *rso_config,
6948 				   struct rso_user_config *rso_usr_cfg)
6949 {
6950 	uint32_t cmd_type, req_id;
6951 	struct nlattr *tb[MAX_ROAMING_PARAM + 1];
6952 	int ret;
6953 	mac_handle_t mac_handle;
6954 
6955 	if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
6956 				    wlan_hdd_set_roam_param_policy)) {
6957 		hdd_err("Invalid ATTR");
6958 		return -EINVAL;
6959 	}
6960 	/* Parse and fetch Command Type */
6961 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
6962 		hdd_err("roam cmd type failed");
6963 		goto fail;
6964 	}
6965 
6966 	cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
6967 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
6968 		hdd_err("attr request id failed");
6969 		goto fail;
6970 	}
6971 	mac_handle = hdd_ctx->mac_handle;
6972 	req_id = nla_get_u32(
6973 		tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
6974 	hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
6975 	switch (cmd_type) {
6976 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST:
6977 		ret = hdd_set_allow_list(hdd_ctx, rso_config, tb, vdev_id,
6978 					 rso_usr_cfg);
6979 		if (ret)
6980 			goto fail;
6981 		break;
6982 
6983 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
6984 		/* Parse and fetch 5G Boost Threshold */
6985 		if (!tb[PARAM_A_BAND_BOOST_THLD]) {
6986 			hdd_err("5G boost threshold failed");
6987 			goto fail;
6988 		}
6989 		rso_config->raise_rssi_thresh_5g = nla_get_s32(
6990 			tb[PARAM_A_BAND_BOOST_THLD]);
6991 		hdd_debug("5G Boost Threshold (%d)",
6992 			rso_config->raise_rssi_thresh_5g);
6993 		/* Parse and fetch 5G Penalty Threshold */
6994 		if (!tb[PARAM_A_BAND_PELT_THLD]) {
6995 			hdd_err("5G penalty threshold failed");
6996 			goto fail;
6997 		}
6998 		rso_config->drop_rssi_thresh_5g = nla_get_s32(
6999 			tb[PARAM_A_BAND_PELT_THLD]);
7000 		hdd_debug("5G Penalty Threshold (%d)",
7001 			rso_config->drop_rssi_thresh_5g);
7002 		/* Parse and fetch 5G Boost Factor */
7003 		if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
7004 			hdd_err("5G boost Factor failed");
7005 			goto fail;
7006 		}
7007 		rso_config->raise_factor_5g = nla_get_u32(
7008 			tb[PARAM_A_BAND_BOOST_FACTOR]);
7009 		hdd_debug("5G Boost Factor (%d)",
7010 			rso_config->raise_factor_5g);
7011 		/* Parse and fetch 5G Penalty factor */
7012 		if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
7013 			hdd_err("5G Penalty Factor failed");
7014 			goto fail;
7015 		}
7016 		rso_config->drop_factor_5g = nla_get_u32(
7017 			tb[PARAM_A_BAND_PELT_FACTOR]);
7018 		hdd_debug("5G Penalty factor (%d)",
7019 			rso_config->drop_factor_5g);
7020 		/* Parse and fetch 5G Max Boost */
7021 		if (!tb[PARAM_A_BAND_MAX_BOOST]) {
7022 			hdd_err("5G Max Boost failed");
7023 			goto fail;
7024 		}
7025 		rso_config->max_raise_rssi_5g = nla_get_u32(
7026 			tb[PARAM_A_BAND_MAX_BOOST]);
7027 		hdd_debug("5G Max Boost (%d)",
7028 			rso_config->max_raise_rssi_5g);
7029 		/* Parse and fetch Rssi Diff */
7030 		if (!tb[PARAM_ROAM_HISTERESYS]) {
7031 			hdd_err("Rssi Diff failed");
7032 			goto fail;
7033 		}
7034 		rso_config->rssi_diff = nla_get_s32(
7035 			tb[PARAM_ROAM_HISTERESYS]);
7036 		hdd_debug("RSSI Diff (%d)",
7037 			rso_config->rssi_diff);
7038 		/* Parse and fetch Alert Rssi Threshold */
7039 		if (!tb[PARAM_RSSI_TRIGGER]) {
7040 			hdd_err("Alert Rssi Threshold failed");
7041 			goto fail;
7042 		}
7043 		rso_config->alert_rssi_threshold = nla_get_u32(
7044 			tb[PARAM_RSSI_TRIGGER]);
7045 		hdd_debug("Alert RSSI Threshold (%d)",
7046 			rso_config->alert_rssi_threshold);
7047 		sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
7048 				       REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
7049 		break;
7050 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM:
7051 		/* Parse and fetch Activate Good Rssi Roam */
7052 		if (!tb[PARAM_ROAM_ENABLE]) {
7053 			hdd_err("Activate Good Rssi Roam failed");
7054 			goto fail;
7055 		}
7056 		rso_config->good_rssi_roam = nla_get_s32(
7057 			tb[PARAM_ROAM_ENABLE]);
7058 		hdd_debug("Activate Good Rssi Roam (%d)",
7059 			  rso_config->good_rssi_roam);
7060 		sme_update_roam_params(mac_handle, vdev_id, rso_config, NULL,
7061 				       REASON_ROAM_GOOD_RSSI_CHANGED);
7062 		break;
7063 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS:
7064 		ret = hdd_set_bssid_prefs(hdd_ctx, rso_config, tb, vdev_id);
7065 		if (ret)
7066 			goto fail;
7067 		break;
7068 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID:
7069 		ret = hdd_set_denylist_bssid(hdd_ctx, rso_config, tb, vdev_id);
7070 		if (ret)
7071 			goto fail;
7072 		break;
7073 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET:
7074 		ret = hdd_set_roam_with_control_config(hdd_ctx, tb, vdev_id);
7075 		if (ret)
7076 			goto fail;
7077 		break;
7078 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR:
7079 		ret = hdd_clear_roam_control_config(hdd_ctx, tb, vdev_id);
7080 		if (ret)
7081 			goto fail;
7082 		break;
7083 	case QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET:
7084 		ret = hdd_get_roam_control_config(hdd_ctx, tb, vdev_id);
7085 		if (ret)
7086 			goto fail;
7087 		break;
7088 	}
7089 
7090 	return 0;
7091 
7092 fail:
7093 	return -EINVAL;
7094 }
7095 
7096 /**
7097  * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
7098  * @wiphy:                 The wiphy structure
7099  * @wdev:                  The wireless device
7100  * @data:                  Data passed by framework
7101  * @data_len:              Parameters to be configured passed as data
7102  *
7103  * The roaming related parameters are configured by the framework
7104  * using this interface.
7105  *
7106  * Return: Return either success or failure code.
7107  */
7108 static int
7109 __wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
7110 	struct wireless_dev *wdev, const void *data, int data_len)
7111 {
7112 	struct net_device *dev = wdev->netdev;
7113 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7114 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7115 	struct rso_config_params *rso_config;
7116 	struct rso_user_config *rso_usr_cfg = NULL;
7117 
7118 	int ret;
7119 
7120 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7121 		hdd_err("Command not allowed in FTM mode");
7122 		return -EPERM;
7123 	}
7124 
7125 	ret = wlan_hdd_validate_context(hdd_ctx);
7126 	if (ret)
7127 		return ret;
7128 
7129 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7130 		hdd_err("Driver Modules are closed");
7131 		return -EINVAL;
7132 	}
7133 
7134 	rso_config = qdf_mem_malloc(sizeof(*rso_config));
7135 	if (!rso_config)
7136 		return -ENOMEM;
7137 
7138 	rso_usr_cfg = qdf_mem_malloc(sizeof(*rso_usr_cfg));
7139 	if (!rso_usr_cfg)
7140 		return -ENOMEM;
7141 
7142 	ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
7143 				      adapter->deflink->vdev_id, rso_config,
7144 				      rso_usr_cfg);
7145 	qdf_mem_free(rso_config);
7146 	qdf_mem_free(rso_usr_cfg);
7147 
7148 	if (ret)
7149 		goto fail;
7150 
7151 	return 0;
7152 fail:
7153 	return ret;
7154 }
7155 #undef PARAM_NUM_NW
7156 #undef PARAM_SET_BSSID
7157 #undef PARAM_SET_BSSID_HINT
7158 #undef PARAM_SSID_LIST
7159 #undef PARAM_LIST_SSID
7160 #undef MAX_ROAMING_PARAM
7161 #undef PARAM_NUM_BSSID
7162 #undef PARAM_BSSID_PREFS
7163 #undef PARAM_ROAM_BSSID
7164 #undef PARAM_RSSI_MODIFIER
7165 #undef PARAMS_NUM_BSSID
7166 #undef PARAM_BSSID_PARAMS
7167 #undef PARAM_A_BAND_BOOST_THLD
7168 #undef PARAM_A_BAND_PELT_THLD
7169 #undef PARAM_A_BAND_BOOST_FACTOR
7170 #undef PARAM_A_BAND_PELT_FACTOR
7171 #undef PARAM_A_BAND_MAX_BOOST
7172 #undef PARAM_ROAM_HISTERESYS
7173 #undef PARAM_RSSI_TRIGGER
7174 #undef PARAM_ROAM_ENABLE
7175 
7176 
7177 /**
7178  * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
7179  * @wiphy:   pointer to wireless wiphy structure.
7180  * @wdev:    pointer to wireless_dev structure.
7181  * @data:    Pointer to the data to be passed via vendor interface
7182  * @data_len:Length of the data to be passed
7183  *
7184  * Return:   Return the Success or Failure code.
7185  */
7186 static int
7187 wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
7188 				struct wireless_dev *wdev,
7189 				const void *data,
7190 				int data_len)
7191 {
7192 	int errno;
7193 	struct osif_vdev_sync *vdev_sync;
7194 
7195 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7196 	if (errno)
7197 		return errno;
7198 
7199 	errno = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
7200 							data, data_len);
7201 
7202 	osif_vdev_sync_op_stop(vdev_sync);
7203 
7204 	return errno;
7205 }
7206 
7207 #define RATEMASK_PARAMS_TYPE_MAX 4
7208 #define RATEMASK_PARAMS_BITMAP_MAX 16
7209 #define RATEMASK_PARAMS_MAX QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX
7210 const struct nla_policy wlan_hdd_set_ratemask_param_policy[
7211 			RATEMASK_PARAMS_MAX + 1] = {
7212 	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST] = {.type = NLA_NESTED},
7213 	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE] = {.type = NLA_U8},
7214 	[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP] = {.type = NLA_BINARY,
7215 					.len = RATEMASK_PARAMS_BITMAP_MAX},
7216 };
7217 
7218 /**
7219  * hdd_set_ratemask_params() - parse ratemask params
7220  * @hdd_ctx: HDD context
7221  * @data: ratemask attribute payload
7222  * @data_len: length of @data
7223  * @vdev: vdev to modify
7224  *
7225  * Return: 0 on success; error number on failure
7226  */
7227 static int hdd_set_ratemask_params(struct hdd_context *hdd_ctx,
7228 				   const void *data, int data_len,
7229 				   struct wlan_objmgr_vdev *vdev)
7230 {
7231 	struct nlattr *tb[RATEMASK_PARAMS_MAX + 1];
7232 	struct nlattr *tb2[RATEMASK_PARAMS_MAX + 1];
7233 	struct nlattr *curr_attr;
7234 	int ret, rem;
7235 	struct config_ratemask_params rate_params[RATEMASK_PARAMS_TYPE_MAX];
7236 	uint8_t ratemask_type, num_ratemask = 0, len;
7237 	uint32_t bitmap[RATEMASK_PARAMS_BITMAP_MAX / 4];
7238 
7239 	ret = wlan_cfg80211_nla_parse(tb,
7240 				      RATEMASK_PARAMS_MAX,
7241 				      data, data_len,
7242 				      wlan_hdd_set_ratemask_param_policy);
7243 	if (ret) {
7244 		hdd_err("Invalid ATTR");
7245 		return -EINVAL;
7246 	}
7247 
7248 	if (!tb[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST]) {
7249 		hdd_err("ratemask array attribute not present");
7250 		return -EINVAL;
7251 	}
7252 
7253 	memset(rate_params, 0, (RATEMASK_PARAMS_TYPE_MAX *
7254 				sizeof(struct config_ratemask_params)));
7255 
7256 	nla_for_each_nested(curr_attr,
7257 			    tb[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_LIST],
7258 			    rem) {
7259 		if (num_ratemask >= RATEMASK_PARAMS_TYPE_MAX) {
7260 			hdd_err("Exceeding ratemask_list_param_num value");
7261 			return -EINVAL;
7262 		}
7263 
7264 		if (wlan_cfg80211_nla_parse(
7265 				tb2, RATEMASK_PARAMS_MAX,
7266 				nla_data(curr_attr), nla_len(curr_attr),
7267 				wlan_hdd_set_ratemask_param_policy)) {
7268 			hdd_err("nla_parse failed");
7269 			return -EINVAL;
7270 		}
7271 
7272 		if (!tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE]) {
7273 			hdd_err("type attribute not present");
7274 			return -EINVAL;
7275 		}
7276 
7277 		if (!tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP]) {
7278 			hdd_err("bitmap attribute not present");
7279 			return -EINVAL;
7280 		}
7281 
7282 		ratemask_type =
7283 		 nla_get_u8(tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_TYPE]);
7284 		if (ratemask_type >= RATEMASK_PARAMS_TYPE_MAX) {
7285 			hdd_err("invalid ratemask type");
7286 			return -EINVAL;
7287 		}
7288 
7289 		len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP]);
7290 		qdf_mem_zero(bitmap, sizeof(bitmap));
7291 		nla_memcpy(bitmap,
7292 			   tb2[QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_BITMAP],
7293 			   len);
7294 
7295 		hdd_debug("rate_type:%d, lower32 0x%x, lower32_2 0x%x, higher32 0x%x, higher32_2 0x%x",
7296 			  ratemask_type, bitmap[0], bitmap[1],
7297 			  bitmap[2], bitmap[3]);
7298 
7299 		rate_params[num_ratemask].type = ratemask_type;
7300 		rate_params[num_ratemask].lower32 = bitmap[0];
7301 		rate_params[num_ratemask].lower32_2 = bitmap[1];
7302 		rate_params[num_ratemask].higher32 = bitmap[2];
7303 		rate_params[num_ratemask].higher32_2 = bitmap[3];
7304 
7305 		num_ratemask += 1;
7306 	}
7307 
7308 	ret = ucfg_set_ratemask_params(vdev, num_ratemask, rate_params);
7309 	if (ret)
7310 		hdd_err("ucfg_set_ratemask_params failed");
7311 	return ret;
7312 }
7313 
7314 /**
7315  * __wlan_hdd_cfg80211_set_ratemask_config() - Ratemask parameters
7316  * @wiphy:                 The wiphy structure
7317  * @wdev:                  The wireless device
7318  * @data:                  Data passed by framework
7319  * @data_len:              Parameters to be configured passed as data
7320  *
7321  * The ratemask parameters are configured by the framework
7322  * using this interface.
7323  *
7324  * Return: Return either success or failure code.
7325  */
7326 static int
7327 __wlan_hdd_cfg80211_set_ratemask_config(struct wiphy *wiphy,
7328 					struct wireless_dev *wdev,
7329 					const void *data, int data_len)
7330 {
7331 	struct net_device *dev = wdev->netdev;
7332 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7333 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7334 	struct wlan_objmgr_vdev *vdev;
7335 	int ret;
7336 
7337 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7338 		hdd_err("Command not allowed in FTM mode");
7339 		return -EPERM;
7340 	}
7341 
7342 	ret = wlan_hdd_validate_context(hdd_ctx);
7343 	if (ret)
7344 		return ret;
7345 
7346 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7347 		hdd_err("Driver Modules are closed");
7348 		return -EINVAL;
7349 	}
7350 
7351 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
7352 					   WLAN_OSIF_POWER_ID);
7353 	if (!vdev) {
7354 		hdd_err("vdev not present");
7355 		return -EINVAL;
7356 	}
7357 
7358 	ret = hdd_set_ratemask_params(hdd_ctx, data, data_len, vdev);
7359 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
7360 	if (ret)
7361 		goto fail;
7362 
7363 	return 0;
7364 fail:
7365 	return ret;
7366 }
7367 
7368 /**
7369  * wlan_hdd_cfg80211_set_ratemask_config() - set ratemask config
7370  * @wiphy:   pointer to wireless wiphy structure.
7371  * @wdev:    pointer to wireless_dev structure.
7372  * @data:    Pointer to the data to be passed via vendor interface
7373  * @data_len:Length of the data to be passed
7374  *
7375  * Return:   Return the Success or Failure code.
7376  */
7377 static int
7378 wlan_hdd_cfg80211_set_ratemask_config(struct wiphy *wiphy,
7379 				      struct wireless_dev *wdev,
7380 				      const void *data,
7381 				      int data_len)
7382 {
7383 	int errno;
7384 	struct osif_vdev_sync *vdev_sync;
7385 
7386 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7387 	if (errno)
7388 		return errno;
7389 
7390 	errno = __wlan_hdd_cfg80211_set_ratemask_config(wiphy, wdev,
7391 							data, data_len);
7392 
7393 	osif_vdev_sync_op_stop(vdev_sync);
7394 
7395 	return errno;
7396 }
7397 
7398 #define PWR_SAVE_FAIL_CMD_INDEX \
7399 	QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
7400 
7401 void hdd_chip_pwr_save_fail_detected_cb(hdd_handle_t hdd_handle,
7402 			struct chip_pwr_save_fail_detected_params
7403 			*data)
7404 {
7405 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
7406 	struct sk_buff *skb;
7407 	int flags = cds_get_gfp_flags();
7408 
7409 	hdd_enter();
7410 
7411 	if (wlan_hdd_validate_context(hdd_ctx))
7412 		return;
7413 
7414 	if (!data) {
7415 		hdd_debug("data is null");
7416 		return;
7417 	}
7418 
7419 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
7420 					       NLMSG_HDRLEN +
7421 					       sizeof(uint32_t) +
7422 					       NLMSG_HDRLEN,
7423 					       PWR_SAVE_FAIL_CMD_INDEX, flags);
7424 	if (!skb) {
7425 		hdd_info("wlan_cfg80211_vendor_event_alloc failed");
7426 		return;
7427 	}
7428 
7429 	hdd_debug("failure reason code: %u", data->failure_reason_code);
7430 
7431 	if (nla_put_u32(skb,
7432 		QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
7433 		data->failure_reason_code))
7434 		goto fail;
7435 
7436 	wlan_cfg80211_vendor_event(skb, flags);
7437 	hdd_exit();
7438 	return;
7439 
7440 fail:
7441 	wlan_cfg80211_vendor_free_skb(skb);
7442 }
7443 #undef PWR_SAVE_FAIL_CMD_INDEX
7444 
7445 const struct nla_policy
7446 wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
7447 				       +1] = {
7448 	[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
7449 };
7450 
7451 /**
7452  *  wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
7453  *  @hdd_ctx:      HDD context
7454  *  @device_mode:    device mode
7455  *  Return:         bool
7456  */
7457 static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
7458 						   enum QDF_OPMODE device_mode)
7459 {
7460 	struct hdd_adapter *adapter, *next_adapter = NULL;
7461 	struct hdd_ap_ctx *ap_ctx;
7462 	struct hdd_station_ctx *sta_ctx;
7463 	wlan_net_dev_ref_dbgid dbgid =
7464 				NET_DEV_HOLD_CHECK_DFS_CHANNEL_FOR_ADAPTER;
7465 	struct wlan_hdd_link_info *link_info;
7466 
7467 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
7468 					   dbgid) {
7469 		if (adapter->device_mode != device_mode)
7470 			goto next_adapter;
7471 
7472 		hdd_adapter_for_each_active_link_info(adapter, link_info) {
7473 			if (device_mode == QDF_SAP_MODE) {
7474 				ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
7475 				/*
7476 				 *  if there is SAP already running on
7477 				 *  DFS channel, do not disable scan on
7478 				 *  dfs channels. Note that with SAP on DFS,
7479 				 *  there cannot be conurrency on single radio.
7480 				 *  But then we can have multiple radios !!
7481 				 *
7482 				 *  Indoor channels are also marked DFS,
7483 				 *  therefore check if the channel has
7484 				 *  REGULATORY_CHAN_RADAR channel flag to
7485 				 *  identify if the channel is DFS
7486 				 */
7487 				if (wlan_reg_is_dfs_for_freq(
7488 						hdd_ctx->pdev,
7489 						ap_ctx->operating_chan_freq)) {
7490 					hdd_err("SAP running on DFS channel");
7491 					hdd_adapter_dev_put_debug(adapter,
7492 								  dbgid);
7493 					if (next_adapter)
7494 						hdd_adapter_dev_put_debug(
7495 								next_adapter,
7496 								dbgid);
7497 					return true;
7498 				}
7499 			}
7500 
7501 			if (device_mode == QDF_STA_MODE) {
7502 				sta_ctx =
7503 					WLAN_HDD_GET_STATION_CTX_PTR(link_info);
7504 				/*
7505 				 *  if STA is already connected on DFS channel,
7506 				 *  do not disable scan on dfs channels.
7507 				 *
7508 				 *  Indoor channels are also marked DFS,
7509 				 *  therefore check if the channel has
7510 				 *  REGULATORY_CHAN_RADAR channel flag to
7511 				 *  identify if the channel is DFS
7512 				 */
7513 				if (hdd_cm_is_vdev_associated(link_info) &&
7514 				    wlan_reg_is_dfs_for_freq(
7515 					    hdd_ctx->pdev,
7516 					    sta_ctx->conn_info.chan_freq)) {
7517 					hdd_err("client connected on DFS channel");
7518 					hdd_adapter_dev_put_debug(adapter,
7519 								  dbgid);
7520 					if (next_adapter)
7521 						hdd_adapter_dev_put_debug(
7522 								next_adapter,
7523 								dbgid);
7524 					return true;
7525 				}
7526 			}
7527 		}
7528 next_adapter:
7529 		hdd_adapter_dev_put_debug(adapter, dbgid);
7530 	}
7531 
7532 	return false;
7533 }
7534 
7535 /**
7536  * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
7537  * @hdd_ctx: HDD context within host driver
7538  * @enable_dfs_channels: If true, DFS channels can be used for scanning
7539  *
7540  * Loops through devices to see who is operating on DFS channels
7541  * and then disables/enables DFS channels.
7542  * Fails the disable request if any device is active on a DFS channel.
7543  *
7544  * Return: 0 or other error codes.
7545  */
7546 
7547 int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
7548 				  bool enable_dfs_channels)
7549 {
7550 	QDF_STATUS status;
7551 	bool err;
7552 	mac_handle_t mac_handle;
7553 	bool enable_dfs_scan = true;
7554 
7555 	ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
7556 						&enable_dfs_scan);
7557 
7558 	if (enable_dfs_channels == enable_dfs_scan) {
7559 		hdd_debug("DFS channels are already %s",
7560 			  enable_dfs_channels ? "enabled" : "disabled");
7561 		return 0;
7562 	}
7563 
7564 	if (!enable_dfs_channels) {
7565 		err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
7566 							     QDF_STA_MODE);
7567 		if (err)
7568 			return -EOPNOTSUPP;
7569 
7570 		err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
7571 							     QDF_SAP_MODE);
7572 		if (err)
7573 			return -EOPNOTSUPP;
7574 	}
7575 
7576 	ucfg_scan_cfg_set_dfs_chan_scan_allowed(hdd_ctx->psoc,
7577 						enable_dfs_channels);
7578 
7579 	mac_handle = hdd_ctx->mac_handle;
7580 	status = sme_enable_dfs_chan_scan(mac_handle, enable_dfs_channels);
7581 	if (QDF_IS_STATUS_ERROR(status)) {
7582 		hdd_err("Failed to set DFS channel scan flag to %d",
7583 			enable_dfs_channels);
7584 		return qdf_status_to_os_return(status);
7585 	}
7586 
7587 	hdd_abort_mac_scan_all_adapters(hdd_ctx);
7588 
7589 	/* pass dfs channel status to regulatory component */
7590 	status = ucfg_reg_enable_dfs_channels(hdd_ctx->pdev,
7591 					      enable_dfs_channels);
7592 
7593 	if (QDF_IS_STATUS_ERROR(status))
7594 		hdd_err("Failed to %s DFS channels",
7595 			enable_dfs_channels ? "enable" : "disable");
7596 
7597 	return qdf_status_to_os_return(status);
7598 }
7599 
7600 /**
7601  *  __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
7602  *  @wiphy:          corestack handler
7603  *  @wdev:           wireless device
7604  *  @data:           data
7605  *  @data_len:       data length
7606  *  Return:         success(0) or reason code for failure
7607  */
7608 static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
7609 						     struct wireless_dev *wdev,
7610 						     const void *data,
7611 						     int data_len)
7612 {
7613 	struct net_device *dev = wdev->netdev;
7614 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
7615 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
7616 	int ret_val;
7617 	uint32_t no_dfs_flag = 0;
7618 	bool enable_dfs_scan = true;
7619 	hdd_enter_dev(dev);
7620 
7621 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7622 		hdd_err("Command not allowed in FTM mode");
7623 		return -EPERM;
7624 	}
7625 
7626 	ret_val = wlan_hdd_validate_context(hdd_ctx);
7627 	if (ret_val)
7628 		return ret_val;
7629 
7630 	if (wlan_cfg80211_nla_parse(tb,
7631 				    QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
7632 				    data, data_len,
7633 				    wlan_hdd_set_no_dfs_flag_config_policy)) {
7634 		hdd_err("invalid attr");
7635 		return -EINVAL;
7636 	}
7637 
7638 	if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
7639 		hdd_err("attr dfs flag failed");
7640 		return -EINVAL;
7641 	}
7642 
7643 	no_dfs_flag = nla_get_u32(
7644 		tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
7645 
7646 	hdd_debug("DFS flag: %d", no_dfs_flag);
7647 
7648 	if (no_dfs_flag > 1) {
7649 		hdd_err("invalid value of dfs flag");
7650 		return -EINVAL;
7651 	}
7652 	ucfg_scan_cfg_get_dfs_chan_scan_allowed(hdd_ctx->psoc,
7653 						&enable_dfs_scan);
7654 
7655 	if (enable_dfs_scan) {
7656 		ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
7657 	} else {
7658 		if ((!no_dfs_flag) != enable_dfs_scan) {
7659 			hdd_err("DFS chan ini configured %d, no dfs flag: %d",
7660 				enable_dfs_scan,
7661 				no_dfs_flag);
7662 			return -EINVAL;
7663 		}
7664 	}
7665 
7666 	return ret_val;
7667 }
7668 
7669 /**
7670  * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
7671  *
7672  * @wiphy: wiphy device pointer
7673  * @wdev: wireless device pointer
7674  * @data: Vendor command data buffer
7675  * @data_len: Buffer length
7676  *
7677  * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
7678  * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
7679  *
7680  * Return: EOK or other error codes.
7681  */
7682 
7683 static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
7684 						   struct wireless_dev *wdev,
7685 						   const void *data,
7686 						   int data_len)
7687 {
7688 	struct osif_psoc_sync *psoc_sync;
7689 	int errno;
7690 
7691 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
7692 	if (errno)
7693 		return errno;
7694 
7695 	errno = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
7696 							  data, data_len);
7697 
7698 	osif_psoc_sync_op_stop(psoc_sync);
7699 
7700 	return errno;
7701 }
7702 
7703 const struct nla_policy
7704 wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
7705 	[QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
7706 };
7707 
7708 /**
7709  * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
7710  * @wiphy: wiphy device pointer
7711  * @wdev: wireless device pointer
7712  * @data: Vendor command data buffer
7713  * @data_len: Buffer length
7714  *
7715  * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
7716  * setup WISA Mode features.
7717  *
7718  * Return: Success(0) or reason code for failure
7719  */
7720 static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
7721 		struct wireless_dev *wdev, const void *data, int data_len)
7722 {
7723 	struct net_device *dev = wdev->netdev;
7724 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7725 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
7726 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
7727 	struct sir_wisa_params wisa;
7728 	int ret_val;
7729 	QDF_STATUS status;
7730 	bool wisa_mode;
7731 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
7732 	mac_handle_t mac_handle;
7733 
7734 	hdd_enter_dev(dev);
7735 	ret_val = wlan_hdd_validate_context(hdd_ctx);
7736 	if (ret_val)
7737 		goto err;
7738 
7739 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7740 		hdd_err("Command not allowed in FTM mode");
7741 		return -EPERM;
7742 	}
7743 
7744 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
7745 				    data_len, wlan_hdd_wisa_cmd_policy)) {
7746 		hdd_err("Invalid WISA cmd attributes");
7747 		ret_val = -EINVAL;
7748 		goto err;
7749 	}
7750 	if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
7751 		hdd_err("Invalid WISA mode");
7752 		ret_val = -EINVAL;
7753 		goto err;
7754 	}
7755 
7756 	wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
7757 	hdd_debug("WISA Mode: %d", wisa_mode);
7758 	wisa.mode = wisa_mode;
7759 	wisa.vdev_id = adapter->deflink->vdev_id;
7760 	mac_handle = hdd_ctx->mac_handle;
7761 	status = sme_set_wisa_params(mac_handle, &wisa);
7762 	if (!QDF_IS_STATUS_SUCCESS(status)) {
7763 		hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
7764 		ret_val = -EINVAL;
7765 	}
7766 	if (QDF_IS_STATUS_SUCCESS(status) || !wisa_mode)
7767 		cdp_set_wisa_mode(soc, adapter->deflink->vdev_id, wisa_mode);
7768 err:
7769 	hdd_exit();
7770 	return ret_val;
7771 }
7772 
7773 /**
7774  * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
7775  * @wiphy:          corestack handler
7776  * @wdev:           wireless device
7777  * @data:           data
7778  * @data_len:       data length
7779  *
7780  * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
7781  * setup WISA mode features.
7782  *
7783  * Return: Success(0) or reason code for failure
7784  */
7785 static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
7786 						   struct wireless_dev *wdev,
7787 						   const void *data,
7788 						   int data_len)
7789 {
7790 	int errno;
7791 	struct osif_vdev_sync *vdev_sync;
7792 
7793 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7794 	if (errno)
7795 		return errno;
7796 
7797 	errno = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev,
7798 						    data, data_len);
7799 
7800 	osif_vdev_sync_op_stop(vdev_sync);
7801 
7802 	return errno;
7803 }
7804 
7805 struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
7806 					 struct qdf_mac_addr mac_addr)
7807 {
7808 	struct hdd_station_info *stainfo = NULL;
7809 	int i;
7810 
7811 	for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
7812 		if (!qdf_mem_cmp(&astainfo[i].sta_mac,
7813 				 &mac_addr,
7814 				 QDF_MAC_ADDR_SIZE)) {
7815 			stainfo = &astainfo[i];
7816 			break;
7817 		}
7818 	}
7819 
7820 	return stainfo;
7821 }
7822 
7823 /*
7824  * undef short names defined for get station command
7825  * used by __wlan_hdd_cfg80211_get_station_cmd()
7826  */
7827 #undef STATION_INVALID
7828 #undef STATION_INFO
7829 #undef STATION_ASSOC_FAIL_REASON
7830 #undef STATION_REMOTE
7831 #undef STATION_MAX
7832 #undef LINK_INFO_STANDARD_NL80211_ATTR
7833 #undef AP_INFO_STANDARD_NL80211_ATTR
7834 #undef INFO_ROAM_COUNT
7835 #undef INFO_AKM
7836 #undef WLAN802_11_MODE
7837 #undef AP_INFO_HS20_INDICATION
7838 #undef HT_OPERATION
7839 #undef VHT_OPERATION
7840 #undef INFO_ASSOC_FAIL_REASON
7841 #undef REMOTE_MAX_PHY_RATE
7842 #undef REMOTE_TX_PACKETS
7843 #undef REMOTE_TX_BYTES
7844 #undef REMOTE_RX_PACKETS
7845 #undef REMOTE_RX_BYTES
7846 #undef REMOTE_LAST_TX_RATE
7847 #undef REMOTE_LAST_RX_RATE
7848 #undef REMOTE_WMM
7849 #undef REMOTE_SUPPORTED_MODE
7850 #undef REMOTE_AMPDU
7851 #undef REMOTE_TX_STBC
7852 #undef REMOTE_RX_STBC
7853 #undef REMOTE_CH_WIDTH
7854 #undef REMOTE_SGI_ENABLE
7855 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
7856 #undef REMOTE_PAD
7857 #endif
7858 
7859 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
7860 /**
7861  * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
7862  * @wiphy: pointer to wireless wiphy structure.
7863  * @wdev: pointer to wireless_dev structure.
7864  * @data: Pointer to the Key data
7865  * @data_len:Length of the data passed
7866  *
7867  * This is called when wlan driver needs to save the keys received via
7868  * vendor specific command.
7869  *
7870  * Return: Return the Success or Failure code.
7871  */
7872 static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
7873 					       struct wireless_dev *wdev,
7874 					       const void *data, int data_len)
7875 {
7876 	struct net_device *dev = wdev->netdev;
7877 	struct hdd_adapter *hdd_adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7878 	struct hdd_context *hdd_ctx;
7879 	struct hdd_station_ctx *sta_ctx =
7880 			WLAN_HDD_GET_STATION_CTX_PTR(hdd_adapter->deflink);
7881 	struct wlan_crypto_pmksa pmksa;
7882 	int status;
7883 	mac_handle_t mac_handle;
7884 
7885 	hdd_enter_dev(dev);
7886 
7887 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7888 		hdd_err("Command not allowed in FTM mode");
7889 		return -EPERM;
7890 	}
7891 
7892 	if ((!data) || (data_len <= 0) ||
7893 	    (data_len > MAX_PMK_LEN)) {
7894 		hdd_err("Invalid data");
7895 		return -EINVAL;
7896 	}
7897 
7898 	hdd_ctx = WLAN_HDD_GET_CTX(hdd_adapter);
7899 	if (!hdd_ctx) {
7900 		hdd_err("HDD context is null");
7901 		return -EINVAL;
7902 	}
7903 
7904 	status = wlan_hdd_validate_context(hdd_ctx);
7905 	if (status)
7906 		return status;
7907 
7908 	mac_handle = hdd_ctx->mac_handle;
7909 	qdf_mem_zero(&pmksa, sizeof(pmksa));
7910 	pmksa.pmk_len = data_len;
7911 	qdf_mem_copy(pmksa.pmk, data, data_len);
7912 
7913 	qdf_mem_copy(&pmksa.bssid, &sta_ctx->conn_info.bssid,
7914 		     QDF_MAC_ADDR_SIZE);
7915 
7916 	sme_roam_set_psk_pmk(mac_handle, &pmksa,
7917 			     hdd_adapter->deflink->vdev_id, true);
7918 	qdf_mem_zero(&pmksa, sizeof(pmksa));
7919 	return 0;
7920 }
7921 
7922 /**
7923  * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
7924  * @wiphy:   pointer to wireless wiphy structure.
7925  * @wdev:    pointer to wireless_dev structure.
7926  * @data:    Pointer to the Key data
7927  * @data_len:Length of the data passed
7928  *
7929  * This is called when wlan driver needs to save the keys received via
7930  * vendor specific command.
7931  *
7932  * Return:   Return the Success or Failure code.
7933  */
7934 static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
7935 					     struct wireless_dev *wdev,
7936 					     const void *data, int data_len)
7937 {
7938 	int errno;
7939 	struct osif_vdev_sync *vdev_sync;
7940 
7941 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
7942 	if (errno)
7943 		return errno;
7944 
7945 	errno = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev,
7946 						    data, data_len);
7947 
7948 	osif_vdev_sync_op_stop(vdev_sync);
7949 
7950 	return errno;
7951 }
7952 #endif
7953 
7954 const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
7955 			QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
7956 	[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
7957 	[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
7958 	[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
7959 };
7960 
7961 /**
7962  * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
7963  * @wiphy:   pointer to wireless wiphy structure.
7964  * @wdev:    pointer to wireless_dev structure.
7965  * @data:    Pointer to the data to be passed via vendor interface
7966  * @data_len:Length of the data to be passed
7967  *
7968  * This is called when wlan driver needs to send wifi driver related info
7969  * (driver/fw version) to the user space application upon request.
7970  *
7971  * Return:   Return the Success or Failure code.
7972  */
7973 static int
7974 __wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
7975 				  struct wireless_dev *wdev,
7976 				  const void *data, int data_len)
7977 {
7978 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7979 	struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
7980 	uint8_t *firmware_version = NULL;
7981 	int status;
7982 	struct sk_buff *reply_skb;
7983 	uint32_t skb_len = 0;
7984 	struct pld_soc_info info;
7985 	bool stt_flag = false;
7986 
7987 	hdd_enter_dev(wdev->netdev);
7988 
7989 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7990 		hdd_err("Command not allowed in FTM mode");
7991 		return -EPERM;
7992 	}
7993 
7994 	status = wlan_hdd_validate_context(hdd_ctx);
7995 	if (status)
7996 		return status;
7997 
7998 	if (wlan_cfg80211_nla_parse(tb_vendor,
7999 				    QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
8000 				    data, data_len,
8001 				    qca_wlan_vendor_get_wifi_info_policy)) {
8002 		hdd_err("WIFI_INFO_GET NL CMD parsing failed");
8003 		return -EINVAL;
8004 	}
8005 
8006 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
8007 		hdd_debug("Rcvd req for Driver version");
8008 		skb_len += nla_total_size(strlen(QWLAN_VERSIONSTR) + 1);
8009 	}
8010 
8011 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
8012 		hdd_debug("Rcvd req for FW version");
8013 		if (!pld_get_soc_info(hdd_ctx->parent_dev, &info))
8014 			stt_flag = true;
8015 
8016 		firmware_version = qdf_mem_malloc(SIR_VERSION_STRING_LEN);
8017 		if (!firmware_version)
8018 			return -ENOMEM;
8019 
8020 		snprintf(firmware_version, SIR_VERSION_STRING_LEN,
8021 			 "FW:%d.%d.%d.%d.%d.%d HW:%s STT:%s",
8022 			 hdd_ctx->fw_version_info.major_spid,
8023 			 hdd_ctx->fw_version_info.minor_spid,
8024 			 hdd_ctx->fw_version_info.siid,
8025 			 hdd_ctx->fw_version_info.rel_id,
8026 			 hdd_ctx->fw_version_info.crmid,
8027 			 hdd_ctx->fw_version_info.sub_id,
8028 			 hdd_ctx->target_hw_name,
8029 			 (stt_flag ? info.fw_build_id : " "));
8030 		skb_len += nla_total_size(strlen(firmware_version) + 1);
8031 	}
8032 
8033 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
8034 		hdd_debug("Rcvd req for Radio index");
8035 		skb_len += nla_total_size(sizeof(uint32_t));
8036 	}
8037 
8038 	if (!skb_len) {
8039 		hdd_err("unknown attribute in get_wifi_info request");
8040 		qdf_mem_free(firmware_version);
8041 		return -EINVAL;
8042 	}
8043 
8044 	skb_len += NLMSG_HDRLEN;
8045 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
8046 	if (!reply_skb) {
8047 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
8048 		qdf_mem_free(firmware_version);
8049 		return -ENOMEM;
8050 	}
8051 
8052 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
8053 		if (nla_put_string(reply_skb,
8054 			    QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
8055 			    QWLAN_VERSIONSTR))
8056 			goto error_nla_fail;
8057 	}
8058 
8059 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
8060 		if (nla_put_string(reply_skb,
8061 			    QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
8062 			    firmware_version))
8063 			goto error_nla_fail;
8064 	}
8065 
8066 	if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
8067 		if (nla_put_u32(reply_skb,
8068 				QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
8069 				hdd_ctx->radio_index))
8070 			goto error_nla_fail;
8071 	}
8072 
8073 	qdf_mem_free(firmware_version);
8074 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
8075 
8076 error_nla_fail:
8077 	hdd_err("nla put fail");
8078 	qdf_mem_free(firmware_version);
8079 	wlan_cfg80211_vendor_free_skb(reply_skb);
8080 	return -EINVAL;
8081 }
8082 
8083 /**
8084  * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
8085  * @wiphy:   pointer to wireless wiphy structure.
8086  * @wdev:    pointer to wireless_dev structure.
8087  * @data:    Pointer to the data to be passed via vendor interface
8088  * @data_len:Length of the data to be passed
8089  *
8090  * This is called when wlan driver needs to send wifi driver related info
8091  * (driver/fw version) to the user space application upon request.
8092  *
8093  * Return:   Return the Success or Failure code.
8094  */
8095 static int
8096 wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
8097 		struct wireless_dev *wdev,
8098 		const void *data, int data_len)
8099 {
8100 	struct osif_psoc_sync *psoc_sync;
8101 	int errno;
8102 
8103 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
8104 	if (errno)
8105 		return errno;
8106 
8107 	errno = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
8108 
8109 	osif_psoc_sync_op_stop(psoc_sync);
8110 
8111 	return errno;
8112 }
8113 
8114 const struct nla_policy get_logger_set_policy[
8115 			QCA_WLAN_VENDOR_ATTR_LOGGER_MAX + 1] = {
8116 	[QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED] = {.type = NLA_U32},
8117 };
8118 
8119 /**
8120  * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
8121  * @wiphy:   pointer to wireless wiphy structure.
8122  * @wdev:    pointer to wireless_dev structure.
8123  * @data:    Pointer to the data to be passed via vendor interface
8124  * @data_len:Length of the data to be passed
8125  *
8126  * This is called by userspace to know the supported logger features
8127  *
8128  * Return:   Return the Success or Failure code.
8129  */
8130 static int
8131 __wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
8132 		struct wireless_dev *wdev,
8133 		const void *data, int data_len)
8134 {
8135 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
8136 	int status;
8137 	uint32_t features;
8138 	struct sk_buff *reply_skb = NULL;
8139 	bool enable_ring_buffer;
8140 
8141 	hdd_enter_dev(wdev->netdev);
8142 
8143 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8144 		hdd_err("Command not allowed in FTM mode");
8145 		return -EPERM;
8146 	}
8147 
8148 	status = wlan_hdd_validate_context(hdd_ctx);
8149 	if (status)
8150 		return status;
8151 
8152 	features = 0;
8153 	wlan_mlme_get_status_ring_buffer(hdd_ctx->psoc, &enable_ring_buffer);
8154 	if (enable_ring_buffer) {
8155 		features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
8156 		features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
8157 		features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
8158 		features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
8159 		features |= WIFI_LOGGER_PACKET_FATE_SUPPORTED;
8160 		hdd_debug("Supported logger features: 0x%0x", features);
8161 	} else {
8162 		hdd_info("Ring buffer disable");
8163 	}
8164 
8165 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
8166 							     sizeof(uint32_t) +
8167 							     NLA_HDRLEN +
8168 							     NLMSG_HDRLEN);
8169 	if (!reply_skb) {
8170 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
8171 		return -ENOMEM;
8172 	}
8173 
8174 	if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
8175 				   features)) {
8176 		hdd_err("nla put fail");
8177 		wlan_cfg80211_vendor_free_skb(reply_skb);
8178 		return -EINVAL;
8179 	}
8180 
8181 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
8182 }
8183 
8184 /**
8185  * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
8186  * @wiphy:   pointer to wireless wiphy structure.
8187  * @wdev:    pointer to wireless_dev structure.
8188  * @data:    Pointer to the data to be passed via vendor interface
8189  * @data_len:Length of the data to be passed
8190  *
8191  * This is called by userspace to know the supported logger features
8192  *
8193  * Return:   Return the Success or Failure code.
8194  */
8195 static int
8196 wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
8197 		struct wireless_dev *wdev,
8198 		const void *data, int data_len)
8199 {
8200 	struct osif_psoc_sync *psoc_sync;
8201 	int errno;
8202 
8203 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
8204 	if (errno)
8205 		return errno;
8206 
8207 	errno = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
8208 							    data, data_len);
8209 
8210 	osif_psoc_sync_op_stop(psoc_sync);
8211 
8212 	return errno;
8213 }
8214 
8215 #ifdef WLAN_FEATURE_GTK_OFFLOAD
8216 void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
8217 				      uint8_t *kck_ptr, uint8_t kck_len,
8218 				      uint8_t *kek_ptr, uint32_t kek_len,
8219 				      uint8_t *replay_ctr, bool big_endian)
8220 {
8221 	struct hdd_station_ctx *hdd_sta_ctx;
8222 	uint8_t *buf;
8223 	int i;
8224 	struct pmo_gtk_req *gtk_req = NULL;
8225 	struct wlan_objmgr_vdev *vdev;
8226 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
8227 	struct hdd_context *hdd_ctx =  WLAN_HDD_GET_CTX(adapter);
8228 
8229 	gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
8230 	if (!gtk_req)
8231 		return;
8232 
8233 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
8234 	if (kck_ptr) {
8235 		if (kck_len > sizeof(gtk_req->kck)) {
8236 			kck_len = sizeof(gtk_req->kck);
8237 			QDF_ASSERT(0);
8238 		}
8239 		qdf_mem_copy(gtk_req->kck, kck_ptr, kck_len);
8240 		gtk_req->kck_len = kck_len;
8241 	}
8242 
8243 	if (kek_ptr) {
8244 		/* paranoia */
8245 		if (kek_len > sizeof(gtk_req->kek)) {
8246 			kek_len = sizeof(gtk_req->kek);
8247 			QDF_ASSERT(0);
8248 		}
8249 		qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
8250 	}
8251 
8252 	qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssid);
8253 
8254 	gtk_req->kek_len = kek_len;
8255 	gtk_req->is_fils_connection = hdd_is_fils_connection(hdd_ctx, adapter);
8256 
8257 	/* convert big to little endian since driver work on little endian */
8258 	buf = (uint8_t *)&gtk_req->replay_counter;
8259 	for (i = 0; i < 8; i++)
8260 		buf[7 - i] = replay_ctr[i];
8261 
8262 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
8263 					   WLAN_OSIF_POWER_ID);
8264 	if (!vdev)
8265 		goto end;
8266 	status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
8267 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
8268 	if (status != QDF_STATUS_SUCCESS)
8269 		hdd_err("Failed to cache GTK Offload");
8270 
8271 end:
8272 	qdf_mem_free(gtk_req);
8273 }
8274 #endif
8275 
8276 #ifdef WLAN_CFR_ENABLE
8277 void hdd_cfr_data_send_nl_event(uint8_t vdev_id, uint32_t pid,
8278 				const void *data, uint32_t data_len)
8279 {
8280 	uint32_t len, ret;
8281 	struct sk_buff *vendor_event;
8282 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
8283 	struct wlan_hdd_link_info *link_info;
8284 	struct nlmsghdr *nlhdr;
8285 
8286 	if (!hdd_ctx) {
8287 		hdd_err("HDD context is NULL");
8288 		return;
8289 	}
8290 
8291 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
8292 	if (!link_info) {
8293 		hdd_err("adapter NULL for vdev id %d", vdev_id);
8294 		return;
8295 	}
8296 
8297 	hdd_debug("vdev id %d pid %d data len %d", vdev_id, pid, data_len);
8298 	len = nla_total_size(data_len) + NLMSG_HDRLEN;
8299 	vendor_event = wlan_cfg80211_vendor_event_alloc(
8300 			hdd_ctx->wiphy, &link_info->adapter->wdev, len,
8301 			QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG_INDEX,
8302 			GFP_KERNEL);
8303 
8304 	if (!vendor_event) {
8305 		hdd_err("wlan_cfg80211_vendor_event_alloc failed vdev id %d, data len %d",
8306 			vdev_id, data_len);
8307 		return;
8308 	}
8309 
8310 	ret = nla_put(vendor_event,
8311 		      QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA,
8312 		      data_len, data);
8313 	if (ret) {
8314 		hdd_err("CFR event put fails status %d", ret);
8315 		wlan_cfg80211_vendor_free_skb(vendor_event);
8316 		return;
8317 	}
8318 
8319 	if (pid) {
8320 		nlhdr = nlmsg_hdr(vendor_event);
8321 		if (nlhdr)
8322 			nlhdr->nlmsg_pid = pid;
8323 		else
8324 			hdd_err_rl("nlhdr is null");
8325 	}
8326 
8327 	wlan_cfg80211_vendor_event(vendor_event, GFP_ATOMIC);
8328 }
8329 #endif
8330 
8331 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
8332 void hdd_send_roam_scan_ch_list_event(struct hdd_context *hdd_ctx,
8333 				      uint8_t vdev_id, uint16_t buf_len,
8334 				      uint8_t *buf)
8335 {
8336 	struct sk_buff *vendor_event;
8337 	uint32_t len, ret;
8338 	struct wlan_hdd_link_info *link_info;
8339 
8340 	if (!hdd_ctx) {
8341 		hdd_err_rl("hdd context is null");
8342 		return;
8343 	}
8344 
8345 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
8346 	if (!link_info)
8347 		return;
8348 
8349 	len = nla_total_size(buf_len) + NLMSG_HDRLEN;
8350 	vendor_event =
8351 		wlan_cfg80211_vendor_event_alloc(
8352 			hdd_ctx->wiphy, &link_info->adapter->wdev, len,
8353 			QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO_INDEX,
8354 			GFP_KERNEL);
8355 
8356 	if (!vendor_event) {
8357 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
8358 		return;
8359 	}
8360 
8361 	ret = nla_put(vendor_event,
8362 		      QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_CONNECT_CHANNELS,
8363 		      buf_len, buf);
8364 	if (ret) {
8365 		hdd_err("OEM event put fails status %d", ret);
8366 		wlan_cfg80211_vendor_free_skb(vendor_event);
8367 		return;
8368 	}
8369 
8370 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
8371 }
8372 #endif
8373 
8374 #define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
8375 	((1 << 26) | \
8376 	 (((probe_period) & 0x1fff) << 13) | \
8377 	 ((stay_period) & 0x1fff))
8378 
8379 #define ANT_DIV_SET_SNR_DIFF(snr_diff) \
8380 	((1 << 27) | \
8381 	 ((snr_diff) & 0x1fff))
8382 
8383 #define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
8384 	((1 << 28) | \
8385 	 ((probe_dwell_time) & 0x1fff))
8386 
8387 #define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
8388 	((1 << 29) | \
8389 	 (((mgmt_snr_weight) & 0xff) << 16) | \
8390 	 (((data_snr_weight) & 0xff) << 8) | \
8391 	 ((ack_snr_weight) & 0xff))
8392 
8393 #define RX_REORDER_TIMEOUT_VOICE \
8394 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
8395 #define RX_REORDER_TIMEOUT_VIDEO \
8396 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
8397 #define RX_REORDER_TIMEOUT_BESTEFFORT \
8398 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
8399 #define RX_REORDER_TIMEOUT_BACKGROUND \
8400 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
8401 #define RX_BLOCKSIZE_PEER_MAC \
8402 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
8403 #define RX_BLOCKSIZE_WINLIMIT \
8404 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
8405 
8406 #define CONFIG_CHANNEL_WIDTH \
8407 	QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH
8408 #define CONFIG_MLO_LINK_ID \
8409 	QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID
8410 #define CONFIG_MLO_LINKS \
8411 	QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS
8412 
8413 const struct nla_policy wlan_hdd_wifi_config_policy[
8414 			QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
8415 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS] = {
8416 							.type = NLA_U32},
8417 	[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES] = {.type = NLA_BINARY},
8418 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND] = {.type = NLA_U32},
8419 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_VALUE] = {.type = NLA_U32},
8420 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA] = {.type = NLA_BINARY,
8421 						      .len = 5000 },
8422 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH] = {.type = NLA_U32},
8423 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS] = {.type = NLA_U32},
8424 	[QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX] = {.type = NLA_U32},
8425 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE] = {
8426 		.type = NLA_U32},
8427 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO] = {
8428 		.type = NLA_U32},
8429 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT] = {
8430 		.type = NLA_U32},
8431 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND] = {
8432 		.type = NLA_U32},
8433 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC] =
8434 		VENDOR_NLA_POLICY_MAC_ADDR,
8435 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT] = {
8436 		.type = NLA_U32},
8437 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24] = {
8438 		.type = NLA_U8},
8439 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5] = {
8440 		.type = NLA_U8},
8441 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {
8442 		.type = NLA_U8},
8443 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL] = {.type = NLA_U8},
8444 	[QCA_WLAN_VENDOR_ATTR_CONF_TX_RATE] = {.type = NLA_U16},
8445 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM] = {.type = NLA_U32 },
8446 	[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED] = {
8447 		.type = NLA_U8},
8448 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS] = {.type = NLA_U8 },
8449 	[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
8450 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
8451 	[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
8452 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
8453 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
8454 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
8455 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
8456 	[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
8457 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
8458 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
8459 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
8460 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY] = {
8461 		.type = NLA_U32 },
8462 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
8463 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
8464 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
8465 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
8466 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME] = {
8467 		.type = NLA_U32},
8468 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT] = {
8469 		.type = NLA_U32},
8470 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT] = {
8471 		.type = NLA_U32},
8472 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT] = {
8473 		.type = NLA_U32},
8474 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
8475 	[RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
8476 	[RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
8477 	[RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
8478 	[RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
8479 	[RX_BLOCKSIZE_PEER_MAC] = VENDOR_NLA_POLICY_MAC_ADDR,
8480 	[RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
8481 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
8482 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
8483 	[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER] = {.type = NLA_U8 },
8484 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
8485 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
8486 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
8487 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {
8488 						.type = NLA_U32 },
8489 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
8490 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {
8491 						.type = NLA_U8},
8492 	[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
8493 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
8494 	[QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_U8},
8495 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS] = {.type = NLA_U8},
8496 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY] = {.type = NLA_U32 },
8497 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST] = {
8498 		.type = NLA_BINARY,
8499 		.len = WLAN_MAX_IE_LEN + 2},
8500 	[QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES] = {
8501 		.type = NLA_BINARY,
8502 		.len = SIR_MAC_MAX_ADD_IE_LENGTH + 2},
8503 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON] = {.type = NLA_U8 },
8504 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION] = {.type = NLA_U8 },
8505 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION] = {.type = NLA_U8 },
8506 	[QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC] = {.type = NLA_U8 },
8507 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC] = {.type = NLA_U8 },
8508 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC] = {.type = NLA_U8 },
8509 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE] = {.type = NLA_U32 },
8510 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH] = {.type = NLA_U8 },
8511 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW] = {.type = NLA_U8 },
8512 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NSS] = {.type = NLA_U8 },
8513 	[QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT] = {
8514 		.type = NLA_U8 },
8515 	[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_ITO] = {.type = NLA_U16 },
8516 	[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_SPEC_WAKE_INTERVAL] = {
8517 		.type = NLA_U16 },
8518 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE] = {
8519 		.type = NLA_U8 },
8520 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS] = {.type = NLA_U8 },
8521 	[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS] = {.type = NLA_U8 },
8522 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING] = {.type = NLA_U8 },
8523 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL] = {.type = NLA_S32 },
8524 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS] = {.type = NLA_U8 },
8525 	[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS] = {.type = NLA_U8 },
8526 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY] = {
8527 							.type = NLA_U8 },
8528 	[QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS] = {.type = NLA_U8 },
8529 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD] = {.type = NLA_U8 },
8530 	[QCA_WLAN_VENDOR_ATTR_CONFIG_DBAM] = {.type = NLA_U8 },
8531 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE_FOR_BE_BK] = {
8532 		.type = NLA_U8 },
8533 	[QCA_WLAN_VENDOR_ATTR_CONFIG_BEAMFORMER_PERIODIC_SOUNDING] = {
8534 		.type = NLA_U8 },
8535 	[QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE] = {
8536 		.type = NLA_U8 },
8537 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_EML_CAPABILITY] = {
8538 		.type = NLA_U8},
8539 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_SIMULTANEOUS_LINKS] = {
8540 		.type = NLA_U8},
8541 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_CAPABILITY] = {
8542 		.type = NLA_U8},
8543 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_FUNCTION] = {
8544 		.type = NLA_U8},
8545 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_NUM_LINKS] = {
8546 		.type = NLA_U8},
8547 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MODE] = {
8548 		.type = NLA_U8},
8549 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_ACTIVE_LINKS] = {
8550 		.type = NLA_NESTED},
8551 	[QCA_WLAN_VENDOR_ATTR_CONFIG_EMLSR_MODE_SWITCH] = {
8552 		.type = NLA_U8},
8553 	[QCA_WLAN_VENDOR_ATTR_CONFIG_UL_MU_CONFIG] = {.type = NLA_U8},
8554 	[QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST] = {
8555 		.type = NLA_NESTED},
8556 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS] = {
8557 		.type = NLA_NESTED },
8558 	[QCA_WLAN_VENDOR_ATTR_CONFIG_PEER_AMPDU_CNT] = {.type = NLA_U16},
8559 	[QCA_WLAN_VENDOR_ATTR_CONFIG_TTLM_NEGOTIATION_SUPPORT] = {
8560 		.type = NLA_U8},
8561 	[QCA_WLAN_VENDOR_ATTR_CONFIG_COEX_TRAFFIC_SHAPING_MODE] = {
8562 		.type = NLA_U8},
8563 };
8564 
8565 #define WLAN_MAX_LINK_ID 15
8566 
8567 static const struct nla_policy bandwidth_mlo_policy[
8568 			QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
8569 	[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH] = {
8570 		.type = NLA_U8 },
8571 	[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID] = {
8572 		.type = NLA_U8 },
8573 };
8574 
8575 static const struct nla_policy
8576 qca_wlan_vendor_attr_omi_tx_policy [QCA_WLAN_VENDOR_ATTR_OMI_MAX + 1] = {
8577 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS] =       {.type = NLA_U8 },
8578 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW] =        {.type = NLA_U8 },
8579 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE] = {.type = NLA_U8 },
8580 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS] =      {.type = NLA_U8 },
8581 	[QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE] = {.type = NLA_U8 },
8582 	[QCA_WLAN_VENDOR_ATTR_EHT_OMI_RX_NSS_EXTN] = {.type = NLA_U8 },
8583 	[QCA_WLAN_VENDOR_ATTR_EHT_OMI_CH_BW_EXTN] =  {.type = NLA_U8 },
8584 	[QCA_WLAN_VENDOR_ATTR_EHT_OMI_TX_NSS_EXTN] = {.type = NLA_U8 },
8585 };
8586 
8587 static const struct nla_policy
8588 wlan_oci_override_policy [QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX + 1] = {
8589 	[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE] = {.type = NLA_U8 },
8590 	[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY] = {.type = NLA_U32 },
8591 };
8592 
8593 const struct nla_policy
8594 wlan_hdd_wifi_test_config_policy[
8595 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
8596 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
8597 			.type = NLA_U8},
8598 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
8599 			.type = NLA_U8},
8600 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
8601 			.type = NLA_U8},
8602 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
8603 			.type = NLA_U8},
8604 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
8605 			.type = NLA_U8},
8606 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
8607 			.type = NLA_U8},
8608 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
8609 			.type = NLA_U8},
8610 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE] = {
8611 			.type = NLA_U8},
8612 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
8613 			.type = NLA_U8},
8614 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
8615 			.type = NLA_U16},
8616 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
8617 			.type = NLA_U8},
8618 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
8619 			.type = NLA_U8},
8620 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF] = {
8621 			.type = NLA_U8},
8622 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE] = {
8623 			.type = NLA_U8},
8624 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS] = {
8625 			.type = NLA_U8},
8626 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT] = {
8627 			.type = NLA_U8},
8628 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS] = {
8629 			.type = NLA_U8},
8630 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR] = {
8631 			.type = NLA_U8},
8632 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC] = {
8633 			.type = NLA_U8},
8634 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA] = {
8635 			.type = NLA_U8},
8636 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP] = {
8637 			.type = NLA_U8},
8638 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW] = {
8639 			.type = NLA_U8},
8640 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS] = {
8641 			.type = NLA_U8},
8642 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG] = {
8643 			.type = NLA_FLAG},
8644 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU] = {
8645 			.type = NLA_U8},
8646 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA] = {
8647 			.type = NLA_U8},
8648 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP] = {
8649 			.type = NLA_U8},
8650 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX] = {
8651 			.type = NLA_NESTED},
8652 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU] = {
8653 			.type = NLA_U8},
8654 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS]
8655 			= {.type = NLA_U8},
8656 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT] = {
8657 			.type = NLA_U8},
8658 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP] = {
8659 			.type = NLA_NESTED},
8660 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE] = {
8661 			.type = NLA_NESTED},
8662 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT] = {
8663 			.type = NLA_U8},
8664 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE] = {
8665 			.type = NLA_U8},
8666 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION] = {
8667 			.type = NLA_U8},
8668 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX]
8669 			= {.type = NLA_U8},
8670 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD] = {
8671 			.type = NLA_U16},
8672 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE] = {
8673 			.type = NLA_U8},
8674 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX] = {
8675 			.type = NLA_U8},
8676 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX] = {
8677 			.type = NLA_FLAG},
8678 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED] = {
8679 			.type = NLA_U8},
8680 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA] = {
8681 			.type = NLA_U8},
8682 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE] = {
8683 			.type = NLA_NESTED},
8684 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT] = {
8685 			.type = NLA_U8},
8686 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX] = {
8687 			.type = NLA_U8},
8688 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO] = {
8689 			.type = NLA_U8},
8690 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX] = {
8691 			.type = NLA_U8},
8692 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE]
8693 			= {.type = NLA_U8},
8694 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE]
8695 			= {.type = NLA_U8},
8696 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_11BE_EMLSR_MODE] = {
8697 			.type = NLA_U8},
8698 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BEAMFORMER_PERIODIC_SOUNDING] = {
8699 			.type = NLA_U8},
8700 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_80MHZ] = {
8701 			.type = NLA_U8},
8702 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_160MHZ] = {
8703 			.type = NLA_U8},
8704 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_320MHZ] = {
8705 			.type = NLA_U8},
8706 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EXCLUDE_STA_PROF_IN_PROBE_REQ] = {
8707 			.type = NLA_U8},
8708 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_EHT_TESTBED_DEFAULTS] = {
8709 			.type = NLA_U8},
8710 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MCS] = {
8711 			.type = NLA_U8},
8712 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_TB_SOUNDING_FB_RL] = {
8713 			.type = NLA_U8},
8714 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_OM_CTRL_SUPPORT] = {
8715 			.type = NLA_U8},
8716 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EMLSR_PADDING_DELAY] = {
8717 			.type = NLA_U8},
8718 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FORCE_MLO_POWER_SAVE_BCN_PERIOD] = {
8719 			.type = NLA_U8},
8720 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_STR_TX] = {
8721 			.type = NLA_U8},
8722 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_LINK_POWER_SAVE] = {
8723 			.type = NLA_NESTED},
8724 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MLD_ID_ML_PROBE_REQ] = {
8725 			.type = NLA_U8},
8726 };
8727 
8728 /**
8729  * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
8730  * @hdd_ctx: HDD context
8731  * @adapter: Pointer to HDD adapter
8732  * @ie_data: Pointer to Scan IEs buffer
8733  * @ie_len: Length of Scan IEs
8734  *
8735  * This API is used to store the default scan ies received from
8736  * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
8737  *
8738  * Return: 0 on success; error number otherwise
8739  */
8740 static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
8741 					  struct hdd_adapter *adapter,
8742 					  uint8_t *ie_data, uint16_t ie_len)
8743 {
8744 	struct hdd_scan_info *scan_info = &adapter->scan_info;
8745 	bool add_qcn_ie;
8746 
8747 	if (!scan_info)
8748 		return -EINVAL;
8749 
8750 	if (scan_info->default_scan_ies) {
8751 		qdf_mem_free(scan_info->default_scan_ies);
8752 		scan_info->default_scan_ies = NULL;
8753 	}
8754 
8755 	scan_info->default_scan_ies_len = ie_len;
8756 	ucfg_mlme_get_qcn_ie_support(hdd_ctx->psoc, &add_qcn_ie);
8757 	if (add_qcn_ie)
8758 		ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
8759 
8760 	scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
8761 	if (!scan_info->default_scan_ies) {
8762 		scan_info->default_scan_ies_len = 0;
8763 		return -ENOMEM;
8764 	}
8765 
8766 	qdf_mem_copy(scan_info->default_scan_ies, ie_data,
8767 			  scan_info->default_scan_ies_len);
8768 
8769 	/* Add QCN IE if g_qcn_ie_support INI is enabled */
8770 	if (add_qcn_ie)
8771 		sme_add_qcn_ie(hdd_ctx->mac_handle,
8772 			       scan_info->default_scan_ies,
8773 			       &scan_info->default_scan_ies_len);
8774 
8775 	hdd_debug("Saved default scan IE:len %d",
8776 		  scan_info->default_scan_ies_len);
8777 	qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
8778 				(uint8_t *) scan_info->default_scan_ies,
8779 				scan_info->default_scan_ies_len);
8780 
8781 	return 0;
8782 }
8783 
8784 /**
8785  * wlan_hdd_handle_restrict_offchan_config() -
8786  * Handle wifi configuration attribute :
8787  * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
8788  * @adapter: Pointer to HDD adapter
8789  * @restrict_offchan: Restrict offchannel setting done by
8790  * application
8791  *
8792  * Return: 0 on success; error number otherwise
8793  */
8794 static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
8795 						   u8 restrict_offchan)
8796 {
8797 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8798 	enum QDF_OPMODE dev_mode = adapter->device_mode;
8799 	struct wlan_objmgr_vdev *vdev;
8800 	int ret_val = 0;
8801 
8802 	if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
8803 		hdd_err("Invalid interface type:%d", dev_mode);
8804 		return -EINVAL;
8805 	}
8806 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
8807 	if (!vdev)
8808 		return -EINVAL;
8809 	if (restrict_offchan == 1) {
8810 		u32 vdev_id = wlan_vdev_get_id(vdev);
8811 		enum policy_mgr_con_mode pmode =
8812 		policy_mgr_qdf_opmode_to_pm_con_mode(hdd_ctx->psoc, dev_mode,
8813 						     vdev_id);
8814 		uint32_t freq;
8815 
8816 		wlan_vdev_obj_lock(vdev);
8817 		wlan_vdev_mlme_cap_set(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
8818 		wlan_vdev_obj_unlock(vdev);
8819 		freq = policy_mgr_get_channel(hdd_ctx->psoc, pmode, &vdev_id);
8820 		if (!freq ||
8821 		    wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, freq)) {
8822 			hdd_err("unable to send avoid_freq");
8823 			ret_val = -EINVAL;
8824 		}
8825 		hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
8826 	} else if (restrict_offchan == 0) {
8827 		wlan_vdev_obj_lock(vdev);
8828 		wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
8829 		wlan_vdev_obj_unlock(vdev);
8830 		if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
8831 			hdd_err("unable to clear avoid_freq");
8832 			ret_val = -EINVAL;
8833 		}
8834 		hdd_info("vdev mode %d dnbs disabled", dev_mode);
8835 	} else {
8836 		ret_val = -EINVAL;
8837 		hdd_err("Invalid RESTRICT_OFFCHAN setting");
8838 	}
8839 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
8840 	return ret_val;
8841 }
8842 
8843 /**
8844  * wlan_hdd_cfg80211_wifi_set_reorder_timeout() - set reorder timeout
8845  * @link_info: link info pointer in HDD adapter
8846  * @tb: array of pointer to struct nlattr
8847  *
8848  * Return: 0 on success; error number otherwise
8849  */
8850 static int
8851 wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct wlan_hdd_link_info *link_info,
8852 					   struct nlattr *tb[])
8853 {
8854 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
8855 	int ret_val = 0;
8856 	QDF_STATUS qdf_status;
8857 	struct sir_set_rx_reorder_timeout_val reorder_timeout;
8858 	mac_handle_t mac_handle;
8859 
8860 #define RX_TIMEOUT_VAL_MIN 10
8861 #define RX_TIMEOUT_VAL_MAX 1000
8862 
8863 	if (tb[RX_REORDER_TIMEOUT_VOICE] ||
8864 	    tb[RX_REORDER_TIMEOUT_VIDEO] ||
8865 	    tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
8866 	    tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
8867 
8868 		/* if one is specified, all must be specified */
8869 		if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
8870 		    !tb[RX_REORDER_TIMEOUT_VIDEO] ||
8871 		    !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
8872 		    !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
8873 			hdd_err("four AC timeout val are required MAC");
8874 			return -EINVAL;
8875 		}
8876 
8877 		reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
8878 			tb[RX_REORDER_TIMEOUT_VOICE]);
8879 		reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
8880 			tb[RX_REORDER_TIMEOUT_VIDEO]);
8881 		reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
8882 			tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
8883 		reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
8884 			tb[RX_REORDER_TIMEOUT_BACKGROUND]);
8885 		/* timeout value is required to be in the rang 10 to 1000ms */
8886 		if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
8887 		    reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
8888 		    reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
8889 		    reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
8890 		    reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
8891 		    reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
8892 		    reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
8893 		    reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
8894 			mac_handle = hdd_ctx->mac_handle;
8895 			qdf_status = sme_set_reorder_timeout(mac_handle,
8896 							     &reorder_timeout);
8897 			if (qdf_status != QDF_STATUS_SUCCESS) {
8898 				hdd_err("failed to set reorder timeout err %d",
8899 					qdf_status);
8900 				ret_val = -EPERM;
8901 			}
8902 		} else {
8903 			hdd_err("one of the timeout value is not in range");
8904 			ret_val = -EINVAL;
8905 		}
8906 	}
8907 
8908 	return ret_val;
8909 }
8910 
8911 /**
8912  * wlan_hdd_cfg80211_wifi_set_rx_blocksize() - set rx blocksize
8913  * @link_info: Link info pointer in HDD adapter
8914  * @tb: array of pointer to struct nlattr
8915  *
8916  * Return: 0 on success; error number otherwise
8917  */
8918 static int
8919 wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct wlan_hdd_link_info *link_info,
8920 					struct nlattr *tb[])
8921 {
8922 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
8923 	int ret_val = 0;
8924 	uint32_t set_value;
8925 	QDF_STATUS qdf_status;
8926 	struct sir_peer_set_rx_blocksize rx_blocksize;
8927 	mac_handle_t mac_handle;
8928 
8929 #define WINDOW_SIZE_VAL_MIN 1
8930 #define WINDOW_SIZE_VAL_MAX 64
8931 
8932 	if (tb[RX_BLOCKSIZE_WINLIMIT]) {
8933 
8934 		/* if one is specified, both must be specified */
8935 		if (!tb[RX_BLOCKSIZE_PEER_MAC]) {
8936 			hdd_err("Both Peer MAC and windows limit required");
8937 			return -EINVAL;
8938 		}
8939 
8940 		memcpy(&rx_blocksize.peer_macaddr,
8941 		       nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
8942 		       sizeof(rx_blocksize.peer_macaddr)),
8943 
8944 		rx_blocksize.vdev_id = link_info->vdev_id;
8945 		set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
8946 		/* maximum window size is 64 */
8947 		if (set_value >= WINDOW_SIZE_VAL_MIN &&
8948 		    set_value <= WINDOW_SIZE_VAL_MAX) {
8949 			rx_blocksize.rx_block_ack_win_limit = set_value;
8950 			mac_handle = hdd_ctx->mac_handle;
8951 			qdf_status = sme_set_rx_set_blocksize(mac_handle,
8952 							      &rx_blocksize);
8953 			if (qdf_status != QDF_STATUS_SUCCESS) {
8954 				hdd_err("failed to set aggr sizes err %d",
8955 					qdf_status);
8956 				ret_val = -EPERM;
8957 			}
8958 		} else {
8959 			hdd_err("window size val is not in range");
8960 			ret_val = -EINVAL;
8961 		}
8962 	}
8963 
8964 	return ret_val;
8965 }
8966 
8967 int hdd_set_vdev_phy_mode(struct hdd_adapter *adapter,
8968 			  enum qca_wlan_vendor_phy_mode vendor_phy_mode)
8969 {
8970 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8971 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
8972 	struct wlan_hdd_link_info *link_info = adapter->deflink;
8973 	eCsrPhyMode phymode;
8974 	WMI_HOST_WIFI_STANDARD std;
8975 	enum hdd_dot11_mode dot11_mode;
8976 	uint8_t supported_band;
8977 	int ret;
8978 
8979 	if (hdd_cm_is_vdev_connected(link_info)) {
8980 		hdd_err("Station is connected, command is not supported");
8981 		return -EINVAL;
8982 	}
8983 
8984 	adapter->user_phy_mode = vendor_phy_mode;
8985 
8986 	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &phymode);
8987 	if (ret)
8988 		return ret;
8989 
8990 	ret = hdd_phymode_to_dot11_mode(phymode, &dot11_mode);
8991 	if (ret)
8992 		return ret;
8993 
8994 	ret = hdd_vendor_mode_to_band(vendor_phy_mode, &supported_band,
8995 				      wlan_reg_is_6ghz_supported(psoc));
8996 	if (ret)
8997 		return ret;
8998 
8999 	std = hdd_get_wifi_standard(hdd_ctx, dot11_mode, supported_band);
9000 	hdd_debug("wifi_standard %d, vendor_phy_mode %d", std, vendor_phy_mode);
9001 
9002 	ret = sme_cli_set_command(link_info->vdev_id,
9003 				  wmi_vdev_param_wifi_standard_version,
9004 				  std, VDEV_CMD);
9005 	if (ret) {
9006 		hdd_err("Failed to set standard version to fw");
9007 		return ret;
9008 	}
9009 
9010 	ucfg_mlme_set_vdev_wifi_std(hdd_ctx->psoc, link_info->vdev_id, std);
9011 
9012 	return 0;
9013 }
9014 
9015 int hdd_set_phy_mode(struct hdd_adapter *adapter,
9016 		     enum qca_wlan_vendor_phy_mode vendor_phy_mode)
9017 {
9018 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9019 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
9020 	eCsrPhyMode phymode;
9021 	uint8_t supported_band;
9022 	uint32_t bonding_mode;
9023 	int ret = 0;
9024 
9025 	if (!psoc) {
9026 		hdd_err("psoc is NULL");
9027 		return -EINVAL;
9028 	}
9029 
9030 	ret = hdd_vendor_mode_to_phymode(vendor_phy_mode, &phymode);
9031 	if (ret < 0)
9032 		return ret;
9033 
9034 	ret = hdd_vendor_mode_to_band(vendor_phy_mode, &supported_band,
9035 				      wlan_reg_is_6ghz_supported(psoc));
9036 	if (ret < 0)
9037 		return ret;
9038 
9039 	ret = hdd_vendor_mode_to_bonding_mode(vendor_phy_mode, &bonding_mode);
9040 	if (ret < 0)
9041 		return ret;
9042 
9043 	return hdd_update_phymode(adapter, phymode, supported_band,
9044 				  bonding_mode);
9045 }
9046 
9047 /**
9048  * hdd_config_phy_mode() - set PHY mode
9049  * @link_info: Link info pointer in HDD adapter
9050  * @tb: nla attr sent from userspace
9051  *
9052  * Return: 0 on success; error number otherwise
9053  */
9054 static int hdd_config_phy_mode(struct wlan_hdd_link_info *link_info,
9055 			       struct nlattr *tb[])
9056 {
9057 	enum qca_wlan_vendor_phy_mode vendor_phy_mode;
9058 	uint32_t ifindex;
9059 	struct nlattr *phy_mode_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE];
9060 	struct nlattr *ifindex_attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX];
9061 
9062 	if (!phy_mode_attr)
9063 		return 0;
9064 
9065 	vendor_phy_mode = nla_get_u32(phy_mode_attr);
9066 	if (!ifindex_attr)
9067 		return hdd_set_phy_mode(link_info->adapter, vendor_phy_mode);
9068 
9069 	ifindex = nla_get_u32(ifindex_attr);
9070 	if (ifindex == link_info->adapter->dev->ifindex)
9071 		return hdd_set_vdev_phy_mode(link_info->adapter,
9072 					     vendor_phy_mode);
9073 
9074 	hdd_err_rl("ifindex %d, expected ifindex %d", ifindex,
9075 		   link_info->adapter->dev->ifindex);
9076 	return -EINVAL;
9077 }
9078 
9079 /**
9080  * hdd_config_peer_ampdu() - Configure peer A-MPDU count
9081  * @link_info: Link info pointer in HDD adapter
9082  * @tb: nla attr sent from userspace
9083  *
9084  * Return: 0 on success; error number otherwise
9085  */
9086 static int hdd_config_peer_ampdu(struct wlan_hdd_link_info *link_info,
9087 				 struct nlattr *tb[])
9088 {
9089 	struct hdd_adapter *adapter = link_info->adapter;
9090 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9091 	struct nlattr *ampdu_cnt_attr =
9092 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PEER_AMPDU_CNT];
9093 	struct nlattr *ampdu_mac_attr =
9094 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PEER_MAC];
9095 	struct qdf_mac_addr peer_macaddr;
9096 	struct wlan_objmgr_vdev *vdev;
9097 	QDF_STATUS status;
9098 	bool is_sap;
9099 	uint16_t cfg_val;
9100 
9101 	if (!ampdu_cnt_attr)
9102 		return 0;
9103 
9104 	if (adapter->device_mode == QDF_SAP_MODE ||
9105 	    adapter->device_mode == QDF_P2P_GO_MODE)
9106 		is_sap = true;
9107 	else if (adapter->device_mode == QDF_STA_MODE ||
9108 		 adapter->device_mode == QDF_P2P_CLIENT_MODE)
9109 		is_sap = false;
9110 	else {
9111 		hdd_debug("mode not support");
9112 		return -EINVAL;
9113 	}
9114 
9115 	if (is_sap) {
9116 		if (!ampdu_mac_attr) {
9117 			hdd_debug("sap must provide peer mac attr");
9118 			return -EINVAL;
9119 		}
9120 		nla_memcpy(&peer_macaddr, ampdu_mac_attr, QDF_MAC_ADDR_SIZE);
9121 	} else {
9122 		vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
9123 		if (!vdev) {
9124 			hdd_debug("vdev is null");
9125 			return -EINVAL;
9126 		}
9127 		status = wlan_vdev_get_bss_peer_mac(vdev, &peer_macaddr);
9128 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9129 		if (QDF_IS_STATUS_ERROR(status)) {
9130 			hdd_debug("fail to get bss peer mac");
9131 			return -EINVAL;
9132 		}
9133 	}
9134 	cfg_val = nla_get_u16(ampdu_cnt_attr);
9135 	return sme_set_peer_ampdu(hdd_ctx->mac_handle,
9136 				  link_info->vdev_id,
9137 				  &peer_macaddr,
9138 				  cfg_val);
9139 }
9140 
9141 /**
9142  * hdd_set_roam_reason_vsie_status() - enable/disable inclusion of
9143  * roam reason vsie in Reassoc
9144  * @link_info: Link info pointer in adapter
9145  * @attr: nla attr sent by supplicant
9146  *
9147  * Return: 0 on success, negative errno on failure
9148  */
9149 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
9150 static int hdd_set_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
9151 					   const struct nlattr *attr)
9152 {
9153 	uint8_t roam_reason_vsie_enabled;
9154 	int errno;
9155 	QDF_STATUS status = QDF_STATUS_SUCCESS;
9156 	struct hdd_adapter *adapter = link_info->adapter;
9157 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9158 
9159 	if (!hdd_ctx) {
9160 		hdd_err("hdd_ctx failure");
9161 		return -EINVAL;
9162 	}
9163 
9164 	roam_reason_vsie_enabled = nla_get_u8(attr);
9165 	if (roam_reason_vsie_enabled > 1)
9166 		roam_reason_vsie_enabled = 1;
9167 
9168 	status =
9169 		ucfg_mlme_set_roam_reason_vsie_status(hdd_ctx->psoc,
9170 						      roam_reason_vsie_enabled);
9171 	if (QDF_IS_STATUS_ERROR(status)) {
9172 		hdd_err("set roam reason vsie failed");
9173 		return -EINVAL;
9174 	}
9175 
9176 	errno = sme_cli_set_command
9177 			(link_info->vdev_id,
9178 			 wmi_vdev_param_enable_disable_roam_reason_vsie,
9179 			 roam_reason_vsie_enabled, VDEV_CMD);
9180 	if (errno) {
9181 		hdd_err("Failed to set beacon report error vsie");
9182 		status = QDF_STATUS_E_FAILURE;
9183 	}
9184 
9185 	return qdf_status_to_os_return(status);
9186 }
9187 #else
9188 static inline int
9189 hdd_set_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
9190 				const struct nlattr *attr)
9191 {
9192 	return -ENOTSUPP;
9193 }
9194 #endif
9195 
9196 static int hdd_set_ft_over_ds(struct wlan_hdd_link_info *link_info,
9197 			      const struct nlattr *attr)
9198 {
9199 	uint8_t ft_over_ds_enable;
9200 	QDF_STATUS status = QDF_STATUS_SUCCESS;
9201 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9202 
9203 	if (!hdd_ctx) {
9204 		hdd_err("hdd_ctx failure");
9205 		return -EINVAL;
9206 	}
9207 
9208 	ft_over_ds_enable = nla_get_u8(attr);
9209 
9210 	if (ft_over_ds_enable != 0 && ft_over_ds_enable != 1) {
9211 		hdd_err_rl("Invalid ft_over_ds_enable: %d", ft_over_ds_enable);
9212 		return -EINVAL;
9213 	}
9214 
9215 	status = ucfg_mlme_set_ft_over_ds(hdd_ctx->psoc, ft_over_ds_enable);
9216 	if (QDF_IS_STATUS_ERROR(status)) {
9217 		hdd_err("set ft_over_ds failed");
9218 		return -EINVAL;
9219 	}
9220 
9221 	return status;
9222 }
9223 
9224 static int hdd_config_ldpc(struct wlan_hdd_link_info *link_info,
9225 			   const struct nlattr *attr)
9226 {
9227 	uint8_t ldpc;
9228 	int ret;
9229 
9230 	ldpc = nla_get_u8(attr);
9231 
9232 	ret = hdd_set_ldpc(link_info, ldpc);
9233 
9234 	return ret;
9235 }
9236 
9237 static int hdd_config_tx_stbc(struct wlan_hdd_link_info *link_info,
9238 			      const struct nlattr *attr)
9239 {
9240 	uint8_t tx_stbc;
9241 	int ret;
9242 
9243 	tx_stbc = nla_get_u8(attr);
9244 
9245 	ret = hdd_set_tx_stbc(link_info, tx_stbc);
9246 
9247 	return ret;
9248 }
9249 
9250 static int hdd_config_rx_stbc(struct wlan_hdd_link_info *link_info,
9251 			      const struct nlattr *attr)
9252 {
9253 	uint8_t rx_stbc;
9254 	int ret;
9255 
9256 	rx_stbc = nla_get_u8(attr);
9257 
9258 	ret = hdd_set_rx_stbc(link_info, rx_stbc);
9259 
9260 	return ret;
9261 }
9262 
9263 static int hdd_config_access_policy(struct wlan_hdd_link_info *link_info,
9264 				    struct nlattr *tb[])
9265 {
9266 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9267 	struct nlattr *policy_attr =
9268 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY];
9269 	struct nlattr *ielist_attr =
9270 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST];
9271 	uint32_t access_policy;
9272 	uint8_t ie[WLAN_MAX_IE_LEN + 2];
9273 	QDF_STATUS status;
9274 
9275 	/* nothing to do if neither attribute is present */
9276 	if (!ielist_attr && !policy_attr)
9277 		return 0;
9278 
9279 	/* if one is present, both must be present */
9280 	if (!ielist_attr || !policy_attr) {
9281 		hdd_err("Missing attribute for %s",
9282 			policy_attr ?
9283 				"ACCESS_POLICY_IE_LIST" : "ACCESS_POLICY");
9284 		return -EINVAL;
9285 	}
9286 
9287 	/* validate the access policy */
9288 	access_policy = nla_get_u32(policy_attr);
9289 	switch (access_policy) {
9290 	case QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED:
9291 	case QCA_ACCESS_POLICY_DENY_UNLESS_LISTED:
9292 		/* valid */
9293 		break;
9294 	default:
9295 		hdd_err("Invalid value. access_policy %u", access_policy);
9296 		return -EINVAL;
9297 	}
9298 
9299 	/*
9300 	 * ie length is validated by the nla_policy.  need to make a
9301 	 * copy since SME will always read WLAN_MAX_IE_LEN+2 bytes
9302 	 */
9303 	nla_memcpy(ie, ielist_attr, sizeof(ie));
9304 
9305 	hdd_debug("calling sme_update_access_policy_vendor_ie");
9306 	status = sme_update_access_policy_vendor_ie(hdd_ctx->mac_handle,
9307 						    link_info->vdev_id,
9308 						    ie, access_policy);
9309 	if (QDF_IS_STATUS_ERROR(status))
9310 		hdd_err("Failed to set vendor ie and access policy, %d",
9311 			status);
9312 
9313 	return qdf_status_to_os_return(status);
9314 }
9315 
9316 static int hdd_config_mpdu_aggregation(struct wlan_hdd_link_info *link_info,
9317 				       struct nlattr *tb[])
9318 {
9319 	struct nlattr *tx_attr =
9320 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION];
9321 	struct nlattr *rx_attr =
9322 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION];
9323 	uint8_t tx_size, rx_size;
9324 	QDF_STATUS status;
9325 
9326 	/* nothing to do if neither attribute is present */
9327 	if (!tx_attr && !rx_attr)
9328 		return 0;
9329 
9330 	/* if one is present, both must be present */
9331 	if (!tx_attr || !rx_attr) {
9332 		hdd_err("Missing attribute for %s",
9333 			tx_attr ? "RX" : "TX");
9334 		return -EINVAL;
9335 	}
9336 
9337 	tx_size = nla_get_u8(tx_attr);
9338 	rx_size = nla_get_u8(rx_attr);
9339 	if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
9340 	    !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
9341 		hdd_err("TX %d RX %d MPDU aggr size not in range",
9342 			tx_size, rx_size);
9343 
9344 		return -EINVAL;
9345 	}
9346 
9347 	status = wma_set_tx_rx_aggr_size(link_info->vdev_id,
9348 					 tx_size, rx_size,
9349 					 WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU);
9350 
9351 	return qdf_status_to_os_return(status);
9352 }
9353 
9354 static int hdd_config_msdu_aggregation(struct wlan_hdd_link_info *link_info,
9355 				       struct nlattr *tb[])
9356 {
9357 	struct nlattr *tx_attr =
9358 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION];
9359 	struct nlattr *rx_attr =
9360 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION];
9361 	uint8_t tx_size, rx_size;
9362 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9363 	mac_handle_t mac_handle = hdd_ctx->mac_handle;
9364 	QDF_STATUS status;
9365 
9366 	if (!mac_handle) {
9367 		hdd_err("NULL Mac handle");
9368 		return -EINVAL;
9369 	}
9370 
9371 	/* nothing to do if neither attribute is present */
9372 	if (!tx_attr && !rx_attr)
9373 		return 0;
9374 
9375 	/* if one is present, both must be present */
9376 	if (!tx_attr || !rx_attr) {
9377 		hdd_err("Missing attribute for %s",
9378 			tx_attr ? "RX" : "TX");
9379 		return -EINVAL;
9380 	}
9381 
9382 	tx_size = nla_get_u8(tx_attr);
9383 	rx_size = nla_get_u8(rx_attr);
9384 	if (!cfg_in_range(CFG_TX_AGGREGATION_SIZE, tx_size) ||
9385 	    !cfg_in_range(CFG_RX_AGGREGATION_SIZE, rx_size)) {
9386 		hdd_err("TX %d RX %d MSDU aggr size not in range",
9387 			tx_size, rx_size);
9388 
9389 		return -EINVAL;
9390 	}
9391 
9392 	if (tx_size > 1)
9393 		sme_set_amsdu(mac_handle, true);
9394 	else
9395 		sme_set_amsdu(mac_handle, false);
9396 
9397 	hdd_debug("tx size: %d", tx_size);
9398 	status = wma_cli_set_command(link_info->vdev_id,
9399 				     GEN_VDEV_PARAM_AMSDU,
9400 				     tx_size, GEN_CMD);
9401 	if (status) {
9402 		hdd_err("Failed to set AMSDU param to FW, status %d", status);
9403 		return qdf_status_to_os_return(status);
9404 	}
9405 
9406 	return qdf_status_to_os_return(status);
9407 }
9408 
9409 static QDF_STATUS
9410 hdd_populate_vdev_chains(struct wlan_mlme_nss_chains *nss_chains_cfg,
9411 			 uint8_t tx_chains,
9412 			 uint8_t rx_chains,
9413 			 enum nss_chains_band_info band,
9414 			 struct wlan_objmgr_vdev *vdev)
9415 {
9416 	struct wlan_mlme_nss_chains *dynamic_cfg;
9417 
9418 	nss_chains_cfg->num_rx_chains[band] = rx_chains;
9419 	nss_chains_cfg->num_tx_chains[band] = tx_chains;
9420 
9421 	dynamic_cfg = ucfg_mlme_get_dynamic_vdev_config(vdev);
9422 	if (!dynamic_cfg) {
9423 		hdd_err("nss chain dynamic config NULL");
9424 		return QDF_STATUS_E_FAILURE;
9425 	}
9426 	/*
9427 	 * If user gives any nss value, then chains will be adjusted based on
9428 	 * nss (in SME func sme_validate_user_nss_chain_params).
9429 	 * If Chains are not suitable as per current NSS then, we need to
9430 	 * return, and the below logic is added for the same.
9431 	 */
9432 
9433 	if ((dynamic_cfg->rx_nss[band] > rx_chains) ||
9434 	    (dynamic_cfg->tx_nss[band] > tx_chains)) {
9435 		hdd_err("Chains less than nss, configure correct nss first.");
9436 		return QDF_STATUS_E_FAILURE;
9437 	}
9438 
9439 	return QDF_STATUS_SUCCESS;
9440 }
9441 
9442 int
9443 hdd_set_dynamic_antenna_mode(struct wlan_hdd_link_info *link_info,
9444 			     uint8_t num_rx_chains, uint8_t num_tx_chains)
9445 {
9446 	enum nss_chains_band_info band;
9447 	struct wlan_mlme_nss_chains user_cfg;
9448 	QDF_STATUS status;
9449 	mac_handle_t mac_handle;
9450 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9451 	struct wlan_objmgr_vdev *vdev;
9452 	int ret;
9453 
9454 	ret = wlan_hdd_validate_context(hdd_ctx);
9455 	if (0 != ret)
9456 		return ret;
9457 
9458 	mac_handle = hdd_ctx->mac_handle;
9459 	if (!mac_handle) {
9460 		hdd_err("NULL MAC handle");
9461 		return -EINVAL;
9462 	}
9463 
9464 	if (!hdd_is_vdev_in_conn_state(link_info)) {
9465 		hdd_debug("Vdev (id %d) not in connected/started state, cannot accept command",
9466 			  link_info->vdev_id);
9467 		return -EINVAL;
9468 	}
9469 
9470 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
9471 	if (!vdev) {
9472 		hdd_err("vdev is NULL");
9473 		return -EINVAL;
9474 	}
9475 
9476 	qdf_mem_zero(&user_cfg, sizeof(user_cfg));
9477 	for (band = NSS_CHAINS_BAND_2GHZ; band < NSS_CHAINS_BAND_MAX; band++) {
9478 		status = hdd_populate_vdev_chains(&user_cfg,
9479 						  num_tx_chains,
9480 						  num_rx_chains, band, vdev);
9481 		if (QDF_IS_STATUS_ERROR(status)) {
9482 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9483 			return -EINVAL;
9484 		}
9485 	}
9486 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9487 
9488 	status = sme_nss_chains_update(mac_handle,
9489 				       &user_cfg,
9490 				       link_info->vdev_id);
9491 	if (QDF_IS_STATUS_ERROR(status))
9492 		return -EINVAL;
9493 
9494 	return 0;
9495 }
9496 
9497 static int hdd_config_vdev_chains(struct wlan_hdd_link_info *link_info,
9498 				  struct nlattr *tb[])
9499 {
9500 	struct hdd_adapter *adapter = link_info->adapter;
9501 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9502 	uint8_t tx_chains, rx_chains;
9503 	struct nlattr *tx_attr =
9504 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS];
9505 	struct nlattr *rx_attr =
9506 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS];
9507 
9508 	if (!tx_attr && !rx_attr)
9509 		return 0;
9510 
9511 	/* if one is present, both must be present */
9512 	if (!tx_attr || !rx_attr) {
9513 		hdd_err("Missing attribute for %s",
9514 			tx_attr ? "RX" : "TX");
9515 		return -EINVAL;
9516 	}
9517 
9518 	tx_chains = nla_get_u8(tx_attr);
9519 	rx_chains = nla_get_u8(rx_attr);
9520 
9521 	hdd_debug("tx_chains %d rx_chains %d", tx_chains, rx_chains);
9522 	if (hdd_ctx->dynamic_nss_chains_support)
9523 		return hdd_set_dynamic_antenna_mode(link_info,
9524 						    rx_chains, tx_chains);
9525 	return 0;
9526 }
9527 
9528 static int hdd_config_tx_rx_nss(struct wlan_hdd_link_info *link_info,
9529 				struct nlattr *tb[])
9530 {
9531 	uint8_t tx_nss, rx_nss;
9532 	QDF_STATUS status;
9533 
9534 	struct nlattr *tx_attr =
9535 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS];
9536 	struct nlattr *rx_attr =
9537 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS];
9538 
9539 	if (!tx_attr && !rx_attr)
9540 		return 0;
9541 
9542 	/* if one is present, both must be present */
9543 	if (!tx_attr || !rx_attr) {
9544 		hdd_err("Missing attribute for %s",
9545 			tx_attr ? "RX" : "TX");
9546 		return -EINVAL;
9547 	}
9548 
9549 	tx_nss = nla_get_u8(tx_attr);
9550 	rx_nss = nla_get_u8(rx_attr);
9551 	hdd_debug("tx_nss %d rx_nss %d", tx_nss, rx_nss);
9552 	/* Only allow NSS for tx_rx_nss for 1x1, 1x2, 2x2 */
9553 	if (!((tx_nss == 1 && rx_nss == 2) || (tx_nss == 1 && rx_nss == 1) ||
9554 	      (tx_nss == 2 && rx_nss == 2))) {
9555 		hdd_err("Setting tx_nss %d rx_nss %d not allowed", tx_nss,
9556 			rx_nss);
9557 		return -EINVAL;
9558 	}
9559 	status = hdd_update_nss(link_info, tx_nss, rx_nss);
9560 	if (status != QDF_STATUS_SUCCESS) {
9561 		hdd_debug("Can't set tx_nss %d rx_nss %d", tx_nss, rx_nss);
9562 		return -EINVAL;
9563 	}
9564 
9565 	return 0;
9566 }
9567 
9568 #ifdef WLAN_FEATURE_SON
9569 static int hdd_process_generic_set_cmd(struct wlan_hdd_link_info *link_info,
9570 				       struct nlattr *tb[])
9571 {
9572 	struct wireless_dev *wdev;
9573 	struct wiphy *wiphy;
9574 	struct hdd_adapter *adapter = link_info->adapter;
9575 
9576 	if (!adapter)
9577 		return 0;
9578 
9579 	wdev = &adapter->wdev;
9580 	if (!wdev || !wdev->wiphy)
9581 		return 0;
9582 	wiphy = wdev->wiphy;
9583 
9584 	/* Generic command is used by EasyMesh,
9585 	 * route the command to SON module if it is Generic
9586 	 */
9587 	if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND])
9588 		return hdd_son_send_set_wifi_generic_command(wiphy, wdev, tb);
9589 
9590 	return 0;
9591 }
9592 #else
9593 static inline int
9594 hdd_process_generic_set_cmd(struct wlan_hdd_link_info *link_info,
9595 			    struct nlattr *tb[])
9596 {
9597 	return 0;
9598 }
9599 #endif
9600 
9601 static int hdd_config_ani(struct wlan_hdd_link_info *link_info,
9602 			  struct nlattr *tb[])
9603 {
9604 	int errno;
9605 	uint8_t ani_setting_type;
9606 	int32_t ani_level = 0, enable_ani;
9607 	struct nlattr *ani_setting_attr =
9608 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING];
9609 	struct nlattr *ani_level_attr =
9610 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL];
9611 
9612 	if (!ani_setting_attr)
9613 		return 0;
9614 
9615 	ani_setting_type = nla_get_u8(ani_setting_attr);
9616 	if (ani_setting_type != QCA_WLAN_ANI_SETTING_AUTO &&
9617 	    ani_setting_type != QCA_WLAN_ANI_SETTING_FIXED) {
9618 		hdd_err("invalid ani_setting_type %d", ani_setting_type);
9619 		return -EINVAL;
9620 	}
9621 
9622 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_AUTO &&
9623 	    ani_level_attr) {
9624 		hdd_err("Not support to set ani level in QCA_WLAN_ANI_SETTING_AUTO");
9625 		return -EINVAL;
9626 	}
9627 
9628 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_FIXED) {
9629 		if (!ani_level_attr) {
9630 			hdd_err("invalid ani_level_attr");
9631 			return -EINVAL;
9632 		}
9633 		ani_level = nla_get_s32(ani_level_attr);
9634 	}
9635 	hdd_debug("ani_setting_type %u, ani_level %d",
9636 		  ani_setting_type, ani_level);
9637 
9638 	/* ANI (Adaptive noise immunity) */
9639 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_AUTO)
9640 		enable_ani = 1;
9641 	else
9642 		enable_ani = 0;
9643 
9644 	errno = wma_cli_set_command(link_info->vdev_id,
9645 				    wmi_pdev_param_ani_enable,
9646 				    enable_ani, PDEV_CMD);
9647 	if (errno) {
9648 		hdd_err("Failed to set ani enable, errno %d", errno);
9649 		return errno;
9650 	}
9651 
9652 	if (ani_setting_type == QCA_WLAN_ANI_SETTING_FIXED) {
9653 		errno = wma_cli_set_command(link_info->vdev_id,
9654 					    wmi_pdev_param_ani_ofdm_level,
9655 					    ani_level, PDEV_CMD);
9656 		if (errno) {
9657 			hdd_err("Failed to set ani level, errno %d", errno);
9658 			return errno;
9659 		}
9660 	}
9661 
9662 	return 0;
9663 }
9664 
9665 static int hdd_config_ant_div_period(struct wlan_hdd_link_info *link_info,
9666 				     struct nlattr *tb[])
9667 {
9668 	struct nlattr *probe_attr =
9669 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD];
9670 	struct nlattr *stay_attr =
9671 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD];
9672 	uint32_t probe_period, stay_period, ant_div_usrcfg;
9673 	int errno;
9674 
9675 	/* nothing to do if neither attribute is present */
9676 	if (!probe_attr && !stay_attr)
9677 		return 0;
9678 
9679 	/* if one is present, both must be present */
9680 	if (!probe_attr || !stay_attr) {
9681 		hdd_err("Missing attribute for %s",
9682 			probe_attr ? "STAY" : "PROBE");
9683 		return -EINVAL;
9684 	}
9685 
9686 	probe_period = nla_get_u32(probe_attr);
9687 	stay_period = nla_get_u32(stay_attr);
9688 	ant_div_usrcfg = ANT_DIV_SET_PERIOD(probe_period, stay_period);
9689 	hdd_debug("ant div set period: %x", ant_div_usrcfg);
9690 	errno = wma_cli_set_command(link_info->vdev_id,
9691 				    wmi_pdev_param_ant_div_usrcfg,
9692 				    ant_div_usrcfg, PDEV_CMD);
9693 	if (errno)
9694 		hdd_err("Failed to set ant div period, %d", errno);
9695 
9696 	return errno;
9697 }
9698 
9699 static int hdd_config_ant_div_snr_weight(struct wlan_hdd_link_info *link_info,
9700 					 struct nlattr *tb[])
9701 {
9702 	struct nlattr *mgmt_attr =
9703 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT];
9704 	struct nlattr *data_attr =
9705 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT];
9706 	struct nlattr *ack_attr =
9707 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT];
9708 	uint32_t mgmt_snr, data_snr, ack_snr, ant_div_usrcfg;
9709 	int errno;
9710 
9711 	/* nothing to do if none of the attributes are present */
9712 	if (!mgmt_attr && !data_attr && !ack_attr)
9713 		return 0;
9714 
9715 	/* if one is present, all must be present */
9716 	if (!mgmt_attr || !data_attr || !ack_attr) {
9717 		hdd_err("Missing attribute");
9718 		return -EINVAL;
9719 	}
9720 
9721 	mgmt_snr = nla_get_u32(mgmt_attr);
9722 	data_snr = nla_get_u32(data_attr);
9723 	ack_snr = nla_get_u32(ack_attr);
9724 	ant_div_usrcfg = ANT_DIV_SET_WEIGHT(mgmt_snr, data_snr, ack_snr);
9725 	hdd_debug("ant div set weight: %x", ant_div_usrcfg);
9726 	errno = wma_cli_set_command(link_info->vdev_id,
9727 				    wmi_pdev_param_ant_div_usrcfg,
9728 				    ant_div_usrcfg, PDEV_CMD);
9729 	if (errno)
9730 		hdd_err("Failed to set ant div weight, %d", errno);
9731 
9732 	return errno;
9733 }
9734 
9735 static int
9736 hdd_config_fine_time_measurement(struct wlan_hdd_link_info *link_info,
9737 				 const struct nlattr *attr)
9738 {
9739 	struct hdd_adapter *adapter = link_info->adapter;
9740 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9741 	uint32_t user_capability;
9742 	uint32_t target_capability;
9743 	uint32_t final_capability;
9744 	QDF_STATUS status;
9745 
9746 	user_capability = nla_get_u32(attr);
9747 	target_capability = hdd_ctx->fine_time_meas_cap_target;
9748 	final_capability = user_capability & target_capability;
9749 
9750 	status = ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
9751 						  final_capability);
9752 	if (QDF_IS_STATUS_ERROR(status)) {
9753 		hdd_err("Unable to set value, status %d", status);
9754 		return -EINVAL;
9755 	}
9756 
9757 	sme_update_fine_time_measurement_capab(hdd_ctx->mac_handle,
9758 					       link_info->vdev_id,
9759 					       final_capability);
9760 	ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, final_capability);
9761 
9762 	hdd_debug("user: 0x%x, target: 0x%x, final: 0x%x",
9763 		  user_capability, target_capability, final_capability);
9764 
9765 	return 0;
9766 }
9767 
9768 static int hdd_config_dynamic_dtim(struct wlan_hdd_link_info *link_info,
9769 				   const struct nlattr *attr)
9770 {
9771 	struct wlan_objmgr_vdev *vdev;
9772 	uint32_t modulated_dtim;
9773 	QDF_STATUS status;
9774 
9775 	modulated_dtim = nla_get_u32(attr);
9776 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
9777 	if (!vdev)
9778 		return -EINVAL;
9779 
9780 	status = ucfg_pmo_config_modulated_dtim(vdev, modulated_dtim);
9781 
9782 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
9783 
9784 	return qdf_status_to_os_return(status);
9785 }
9786 
9787 static int hdd_config_listen_interval(struct wlan_hdd_link_info *link_info,
9788 				      const struct nlattr *attr)
9789 {
9790 	struct wlan_objmgr_vdev *vdev;
9791 	uint32_t listen_interval;
9792 	QDF_STATUS status;
9793 
9794 	listen_interval = nla_get_u32(attr);
9795 	if (listen_interval > cfg_max(CFG_PMO_ENABLE_DYNAMIC_DTIM)) {
9796 		hdd_err_rl("Invalid value for listen interval - %d",
9797 			   listen_interval);
9798 		return -EINVAL;
9799 	}
9800 
9801 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_PMO_ID);
9802 	if (!vdev)
9803 		return -EINVAL;
9804 
9805 	status = ucfg_pmo_config_listen_interval(vdev, listen_interval);
9806 
9807 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_PMO_ID);
9808 
9809 	return qdf_status_to_os_return(status);
9810 }
9811 
9812 static int hdd_config_lro(struct wlan_hdd_link_info *link_info,
9813 			  const struct nlattr *attr)
9814 {
9815 	struct wlan_objmgr_vdev *vdev;
9816 	uint8_t enable_flag;
9817 	QDF_STATUS status = QDF_STATUS_E_FAULT;
9818 
9819 	enable_flag = nla_get_u8(attr);
9820 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_DP_ID);
9821 	if (vdev) {
9822 		status = osif_dp_lro_set_reset(vdev, enable_flag);
9823 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
9824 	}
9825 
9826 	return qdf_status_to_os_return(status);
9827 }
9828 
9829 static int hdd_config_scan_enable(struct wlan_hdd_link_info *link_info,
9830 				  const struct nlattr *attr)
9831 {
9832 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
9833 	uint8_t enable_flag;
9834 
9835 	enable_flag = nla_get_u8(attr);
9836 	if (enable_flag)
9837 		ucfg_scan_psoc_set_enable(hdd_ctx->psoc, REASON_USER_SPACE);
9838 	else
9839 		ucfg_scan_psoc_set_disable(hdd_ctx->psoc, REASON_USER_SPACE);
9840 
9841 	return 0;
9842 }
9843 
9844 /**
9845  * hdd_config_udp_qos_upgrade_be_bk() - Set UDP QoS threshold for BE/BK AC.
9846  * @link_info: Link info pointer in HDD adapter
9847  * @attr: NL attribute
9848  *
9849  * Returns: 0 on success, -EINVAL on failure
9850  */
9851 static int
9852 hdd_config_udp_qos_upgrade_be_bk(struct wlan_hdd_link_info *link_info,
9853 				 const struct nlattr *attr)
9854 {
9855 	struct hdd_adapter *adapter = link_info->adapter;
9856 	uint8_t priority = nla_get_u8(attr);
9857 
9858 	adapter->udp_qos_upgrade_type = UDP_QOS_UPGRADE_BK_BE;
9859 	return hdd_set_udp_qos_upgrade_config(adapter, priority);
9860 }
9861 
9862 /**
9863  * hdd_config_udp_qos_upgrade_threshold() - NL attribute handler to parse
9864  *					    priority upgrade threshold value.
9865  * @link_info: Link info pointer in adapter
9866  * @attr: NL attribute
9867  *
9868  * Returns: 0 on success, -EINVAL on failure
9869  */
9870 static int
9871 hdd_config_udp_qos_upgrade_threshold(struct wlan_hdd_link_info *link_info,
9872 				     const struct nlattr *attr)
9873 {
9874 	struct hdd_adapter *adapter = link_info->adapter;
9875 	uint8_t priority = nla_get_u8(attr);
9876 
9877 	adapter->udp_qos_upgrade_type = UDP_QOS_UPGRADE_ALL;
9878 	return hdd_set_udp_qos_upgrade_config(adapter, priority);
9879 }
9880 
9881 static enum powersave_mode
9882 hdd_vendor_opm_to_pmo_opm(enum qca_wlan_vendor_opm_mode opm_mode)
9883 {
9884 	switch (opm_mode) {
9885 	case QCA_WLAN_VENDOR_OPM_MODE_DISABLE:
9886 		return PMO_PS_ADVANCED_POWER_SAVE_DISABLE;
9887 	case QCA_WLAN_VENDOR_OPM_MODE_ENABLE:
9888 		return PMO_PS_ADVANCED_POWER_SAVE_ENABLE;
9889 	case QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED:
9890 		return PMO_PS_ADVANCED_POWER_SAVE_USER_DEFINED;
9891 	default:
9892 		hdd_debug("Invalid opm_mode: %d", opm_mode);
9893 		return PMO_PS_ADVANCED_POWER_SAVE_DISABLE;
9894 	}
9895 }
9896 
9897 static int hdd_config_power(struct wlan_hdd_link_info *link_info,
9898 			    struct nlattr *tb[])
9899 {
9900 	struct hdd_adapter *adapter = link_info->adapter;
9901 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9902 	struct wlan_objmgr_vdev *vdev;
9903 	enum qca_wlan_vendor_opm_mode opm_mode;
9904 	struct pmo_ps_params ps_params = {0};
9905 	struct nlattr *power_attr =
9906 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER];
9907 	struct nlattr *opm_attr =
9908 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT];
9909 	struct nlattr *ps_ito_attr =
9910 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_ITO];
9911 	struct nlattr *spec_wake_attr =
9912 		tb[QCA_WLAN_VENDOR_ATTR_CONFIG_OPM_SPEC_WAKE_INTERVAL];
9913 	int ret;
9914 
9915 	hdd_enter_dev(adapter->dev);
9916 
9917 	if (!power_attr && !opm_attr) {
9918 		hdd_err_rl("power attr and opm attr is null");
9919 		return 0;
9920 	}
9921 
9922 
9923 	if (power_attr && opm_attr) {
9924 		hdd_err_rl("Invalid OPM set attribute");
9925 		return -EINVAL;
9926 	}
9927 
9928 	if (!ucfg_pmo_get_default_power_save_mode(hdd_ctx->psoc)) {
9929 		hdd_err_rl("OPM power save is disabled in ini");
9930 		return -EINVAL;
9931 	}
9932 
9933 	opm_mode = power_attr ? nla_get_u8(power_attr) : nla_get_u8(opm_attr);
9934 	hdd_debug("opm_mode %d", opm_mode);
9935 
9936 	if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) {
9937 		if (!ps_ito_attr || !spec_wake_attr) {
9938 			hdd_err_rl("Invalid User defined OPM attributes");
9939 			return -EINVAL;
9940 		}
9941 	}
9942 
9943 	ret = hdd_set_power_config(hdd_ctx, adapter, &opm_mode);
9944 	if (ret)
9945 		return ret;
9946 
9947 	ps_params.opm_mode = hdd_vendor_opm_to_pmo_opm(opm_mode);
9948 	if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED) {
9949 		ps_params.ps_ito = nla_get_u16(ps_ito_attr);
9950 		ps_params.spec_wake = nla_get_u16(spec_wake_attr);
9951 
9952 		if (!ps_params.ps_ito)
9953 			return -EINVAL;
9954 
9955 		hdd_debug("ps_ito %d spec_wake %d opm_mode %d",
9956 			  ps_params.ps_ito, ps_params.spec_wake,
9957 			  ps_params.opm_mode);
9958 
9959 		ret = hdd_set_power_config_params(hdd_ctx, adapter,
9960 						  ps_params.ps_ito,
9961 						  ps_params.spec_wake);
9962 
9963 		if (ret)
9964 			return ret;
9965 	}
9966 
9967 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_POWER_ID);
9968 	if (!vdev) {
9969 		hdd_err("vdev is null");
9970 		return 0;
9971 	}
9972 
9973 	if (opm_mode == QCA_WLAN_VENDOR_OPM_MODE_USER_DEFINED)
9974 		ucfg_pmo_set_ps_params(vdev, &ps_params);
9975 	else
9976 		ucfg_pmo_core_vdev_set_ps_opm_mode(vdev, ps_params.opm_mode);
9977 
9978 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
9979 	return 0;
9980 }
9981 
9982 static int hdd_config_stats_avg_factor(struct wlan_hdd_link_info *link_info,
9983 				       const struct nlattr *attr)
9984 {
9985 	struct hdd_adapter *adapter = link_info->adapter;
9986 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9987 	uint16_t stats_avg_factor;
9988 	QDF_STATUS status;
9989 
9990 	stats_avg_factor = nla_get_u16(attr);
9991 	status = sme_configure_stats_avg_factor(hdd_ctx->mac_handle,
9992 						link_info->vdev_id,
9993 						stats_avg_factor);
9994 
9995 	return qdf_status_to_os_return(status);
9996 }
9997 
9998 static int hdd_config_non_agg_retry(struct wlan_hdd_link_info *link_info,
9999 				    const struct nlattr *attr)
10000 {
10001 	uint8_t retry;
10002 
10003 	retry = nla_get_u8(attr);
10004 	/* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
10005 	retry = (retry > CFG_NON_AGG_RETRY_MAX) ? CFG_NON_AGG_RETRY_MAX :
10006 		((retry < CFG_NON_AGG_RETRY_MIN) ? CFG_NON_AGG_RETRY_MIN :
10007 		  retry);
10008 	hdd_debug("sending Non-Agg Retry Th: %d", retry);
10009 
10010 	return sme_set_vdev_sw_retry(link_info->vdev_id, retry,
10011 				     WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR);
10012 }
10013 
10014 static int hdd_config_agg_retry(struct wlan_hdd_link_info *link_info,
10015 				const struct nlattr *attr)
10016 {
10017 	uint8_t retry;
10018 
10019 	retry = nla_get_u8(attr);
10020 	/* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
10021 	retry = (retry > CFG_AGG_RETRY_MAX) ? CFG_AGG_RETRY_MAX :
10022 		((retry < CFG_AGG_RETRY_MIN) ? CFG_AGG_RETRY_MIN :
10023 		  retry);
10024 	hdd_debug("sending Agg Retry Th: %d", retry);
10025 
10026 	return sme_set_vdev_sw_retry(link_info->vdev_id, retry,
10027 				     WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR);
10028 }
10029 
10030 static int hdd_config_mgmt_retry(struct wlan_hdd_link_info *link_info,
10031 				 const struct nlattr *attr)
10032 {
10033 	uint8_t retry;
10034 	int param_id;
10035 	uint8_t max_mgmt_retry;
10036 
10037 	retry = nla_get_u8(attr);
10038 	max_mgmt_retry = (cfg_max(CFG_MGMT_RETRY_MAX));
10039 	retry = retry > max_mgmt_retry ?
10040 		max_mgmt_retry : retry;
10041 	param_id = wmi_pdev_param_mgmt_retry_limit;
10042 
10043 	return wma_cli_set_command(link_info->vdev_id, param_id,
10044 				   retry, PDEV_CMD);
10045 }
10046 
10047 static int hdd_config_ctrl_retry(struct wlan_hdd_link_info *link_info,
10048 				 const struct nlattr *attr)
10049 {
10050 	uint8_t retry;
10051 	int param_id;
10052 
10053 	retry = nla_get_u8(attr);
10054 	retry = retry > CFG_CTRL_RETRY_MAX ?
10055 		CFG_CTRL_RETRY_MAX : retry;
10056 	param_id = wmi_pdev_param_ctrl_retry_limit;
10057 
10058 	return wma_cli_set_command(link_info->vdev_id, param_id,
10059 				   retry, PDEV_CMD);
10060 }
10061 
10062 static int hdd_config_propagation_delay(struct wlan_hdd_link_info *link_info,
10063 					const struct nlattr *attr)
10064 {
10065 	uint8_t delay;
10066 	uint32_t abs_delay;
10067 	int param_id;
10068 
10069 	delay = nla_get_u8(attr);
10070 	delay = delay > CFG_PROPAGATION_DELAY_MAX ?
10071 				CFG_PROPAGATION_DELAY_MAX : delay;
10072 	abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
10073 	param_id = wmi_pdev_param_propagation_delay;
10074 
10075 	return  wma_cli_set_command(link_info->vdev_id, param_id,
10076 				    abs_delay, PDEV_CMD);
10077 }
10078 
10079 static int
10080 hdd_config_propagation_abs_delay(struct wlan_hdd_link_info *link_info,
10081 				 const struct nlattr *attr)
10082 {
10083 	uint32_t abs_delay;
10084 	int param_id;
10085 
10086 	abs_delay = nla_get_u32(attr);
10087 	param_id = wmi_pdev_param_propagation_delay;
10088 
10089 	return wma_cli_set_command(link_info->vdev_id, param_id,
10090 				   abs_delay, PDEV_CMD);
10091 }
10092 
10093 static int hdd_config_tx_fail_count(struct wlan_hdd_link_info *link_info,
10094 				    const struct nlattr *attr)
10095 {
10096 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
10097 	uint32_t tx_fail_count;
10098 	QDF_STATUS status;
10099 
10100 	tx_fail_count = nla_get_u32(attr);
10101 	if (!tx_fail_count)
10102 		return 0;
10103 
10104 	status = sme_update_tx_fail_cnt_threshold(hdd_ctx->mac_handle,
10105 						  link_info->vdev_id,
10106 						  tx_fail_count);
10107 	if (QDF_IS_STATUS_ERROR(status))
10108 		hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
10109 			status);
10110 
10111 	return qdf_status_to_os_return(status);
10112 }
10113 
10114 static int
10115 hdd_config_channel_avoidance_ind(struct wlan_hdd_link_info *link_info,
10116 				 const struct nlattr *attr)
10117 {
10118 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
10119 	uint8_t set_value;
10120 
10121 	set_value = nla_get_u8(attr);
10122 	hdd_debug("set_value: %d", set_value);
10123 
10124 	return hdd_enable_disable_ca_event(hdd_ctx, set_value);
10125 }
10126 
10127 static int hdd_config_guard_time(struct wlan_hdd_link_info *link_info,
10128 				 const struct nlattr *attr)
10129 {
10130 	struct hdd_adapter *adapter = link_info->adapter;
10131 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10132 	uint32_t guard_time;
10133 	QDF_STATUS status;
10134 
10135 	guard_time = nla_get_u32(attr);
10136 	status = sme_configure_guard_time(hdd_ctx->mac_handle,
10137 					  link_info->vdev_id, guard_time);
10138 
10139 	return qdf_status_to_os_return(status);
10140 }
10141 
10142 static int
10143 hdd_config_scan_default_ies(struct wlan_hdd_link_info *link_info,
10144 			    const struct nlattr *attr)
10145 {
10146 	struct hdd_adapter *adapter = link_info->adapter;
10147 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10148 	uint8_t *scan_ie;
10149 	uint16_t scan_ie_len;
10150 	QDF_STATUS status;
10151 	mac_handle_t mac_handle;
10152 
10153 	scan_ie_len = nla_len(attr);
10154 	hdd_debug("IE len %d session %d device mode %d",
10155 		  scan_ie_len, link_info->vdev_id, adapter->device_mode);
10156 
10157 	if (!scan_ie_len) {
10158 		hdd_err("zero-length IE prohibited");
10159 		return -EINVAL;
10160 	}
10161 
10162 	if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
10163 		hdd_err("IE length %d exceeds max of %d",
10164 			scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
10165 		return -EINVAL;
10166 	}
10167 
10168 	scan_ie = nla_data(attr);
10169 	if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
10170 		hdd_err("Invalid default scan IEs");
10171 		return -EINVAL;
10172 	}
10173 
10174 	if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
10175 					   scan_ie, scan_ie_len))
10176 		hdd_err("Failed to save default scan IEs");
10177 
10178 	if (adapter->device_mode == QDF_STA_MODE) {
10179 		mac_handle = hdd_ctx->mac_handle;
10180 		status = sme_set_default_scan_ie(mac_handle,
10181 						 link_info->vdev_id,
10182 						 scan_ie, scan_ie_len);
10183 		if (QDF_STATUS_SUCCESS != status) {
10184 			hdd_err("failed to set default scan IEs in sme: %d",
10185 				status);
10186 			return -EPERM;
10187 		}
10188 	}
10189 
10190 	return 0;
10191 }
10192 
10193 static int hdd_config_ant_div_ena(struct wlan_hdd_link_info *link_info,
10194 				  const struct nlattr *attr)
10195 {
10196 	uint32_t antdiv_enable;
10197 	int errno;
10198 
10199 	antdiv_enable = nla_get_u32(attr);
10200 	hdd_debug("antdiv_enable: %d", antdiv_enable);
10201 	errno = wma_cli_set_command(link_info->vdev_id,
10202 				    wmi_pdev_param_ena_ant_div,
10203 				    antdiv_enable, PDEV_CMD);
10204 	if (errno)
10205 		hdd_err("Failed to set antdiv_enable, %d", errno);
10206 
10207 	return errno;
10208 }
10209 
10210 static int hdd_config_ant_div_snr_diff(struct wlan_hdd_link_info *link_info,
10211 				       const struct nlattr *attr)
10212 {
10213 	uint32_t ant_div_snr_diff;
10214 	uint32_t ant_div_usrcfg;
10215 	int errno;
10216 
10217 	ant_div_snr_diff = nla_get_u32(attr);
10218 	hdd_debug("snr diff: %x", ant_div_snr_diff);
10219 
10220 	ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(ant_div_snr_diff);
10221 	hdd_debug("usrcfg: %x", ant_div_usrcfg);
10222 
10223 	errno = wma_cli_set_command(link_info->vdev_id,
10224 				    wmi_pdev_param_ant_div_usrcfg,
10225 				    ant_div_usrcfg, PDEV_CMD);
10226 	if (errno)
10227 		hdd_err("Failed to set snr diff, %d", errno);
10228 
10229 	return errno;
10230 }
10231 
10232 static int
10233 hdd_config_ant_div_probe_dwell_time(struct wlan_hdd_link_info *link_info,
10234 				    const struct nlattr *attr)
10235 {
10236 	uint32_t dwell_time;
10237 	uint32_t ant_div_usrcfg;
10238 	int errno;
10239 
10240 	dwell_time = nla_get_u32(attr);
10241 	hdd_debug("dwell time: %x", dwell_time);
10242 
10243 	ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(dwell_time);
10244 	hdd_debug("usrcfg: %x", ant_div_usrcfg);
10245 
10246 	errno = wma_cli_set_command(link_info->vdev_id,
10247 				    wmi_pdev_param_ant_div_usrcfg,
10248 				    ant_div_usrcfg, PDEV_CMD);
10249 	if (errno)
10250 		hdd_err("Failed to set probe dwell time, %d", errno);
10251 
10252 	return errno;
10253 }
10254 
10255 static int hdd_config_ant_div_chain(struct wlan_hdd_link_info *link_info,
10256 				    const struct nlattr *attr)
10257 {
10258 	uint32_t antdiv_chain;
10259 	int errno;
10260 
10261 	antdiv_chain = nla_get_u32(attr);
10262 	hdd_debug("antdiv_chain: %d", antdiv_chain);
10263 
10264 	errno = wma_cli_set_command(link_info->vdev_id,
10265 				    wmi_pdev_param_force_chain_ant,
10266 				    antdiv_chain, PDEV_CMD);
10267 	if (errno)
10268 		hdd_err("Failed to set chain, %d", errno);
10269 
10270 	return errno;
10271 }
10272 
10273 static int hdd_config_ant_div_selftest(struct wlan_hdd_link_info *link_info,
10274 				       const struct nlattr *attr)
10275 {
10276 	uint32_t antdiv_selftest;
10277 	int errno;
10278 
10279 	antdiv_selftest = nla_get_u32(attr);
10280 	hdd_debug("antdiv_selftest: %d", antdiv_selftest);
10281 	errno = wma_cli_set_command(link_info->vdev_id,
10282 				    wmi_pdev_param_ant_div_selftest,
10283 				    antdiv_selftest, PDEV_CMD);
10284 	if (errno)
10285 		hdd_err("Failed to set selftest, %d", errno);
10286 
10287 	return errno;
10288 }
10289 
10290 static int
10291 hdd_config_ant_div_selftest_intvl(struct wlan_hdd_link_info *link_info,
10292 				  const struct nlattr *attr)
10293 {
10294 	uint32_t antdiv_selftest_intvl;
10295 	int errno;
10296 
10297 	antdiv_selftest_intvl = nla_get_u32(attr);
10298 	hdd_debug("antdiv_selftest_intvl: %d", antdiv_selftest_intvl);
10299 	errno = wma_cli_set_command(link_info->vdev_id,
10300 				    wmi_pdev_param_ant_div_selftest_intvl,
10301 				    antdiv_selftest_intvl, PDEV_CMD);
10302 	if (errno)
10303 		hdd_err("Failed to set selftest interval, %d", errno);
10304 
10305 	return errno;
10306 }
10307 
10308 static int
10309 hdd_config_ignore_assoc_disallowed(struct wlan_hdd_link_info *link_info,
10310 				   const struct nlattr *attr)
10311 {
10312 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
10313 	uint8_t ignore_assoc_disallowed;
10314 
10315 	ignore_assoc_disallowed = nla_get_u8(attr);
10316 	hdd_debug("%u", ignore_assoc_disallowed);
10317 	if ((ignore_assoc_disallowed < QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
10318 	    (ignore_assoc_disallowed > QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
10319 		return -EINVAL;
10320 
10321 	sme_set_check_assoc_disallowed(hdd_ctx->mac_handle,
10322 				       !ignore_assoc_disallowed);
10323 
10324 	return 0;
10325 }
10326 
10327 static int hdd_config_restrict_offchannel(struct wlan_hdd_link_info *link_info,
10328 					  const struct nlattr *attr)
10329 {
10330 	uint8_t restrict_offchan;
10331 
10332 	restrict_offchan = nla_get_u8(attr);
10333 	hdd_debug("%u", restrict_offchan);
10334 
10335 	if (restrict_offchan > 1) {
10336 		hdd_err("Invalid value %u", restrict_offchan);
10337 		return -EINVAL;
10338 	}
10339 
10340 	return wlan_hdd_handle_restrict_offchan_config(link_info->adapter,
10341 						       restrict_offchan);
10342 }
10343 
10344 static int
10345 hdd_config_total_beacon_miss_count(struct wlan_hdd_link_info *link_info,
10346 				   const struct nlattr *attr)
10347 {
10348 	struct hdd_adapter *adapter = link_info->adapter;
10349 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10350 	uint8_t first_miss_count;
10351 	uint8_t final_miss_count;
10352 	uint8_t total_miss_count;
10353 	QDF_STATUS status;
10354 
10355 	if (adapter->device_mode != QDF_STA_MODE) {
10356 		hdd_err("Only supported in sta mode");
10357 		return -EINVAL;
10358 	}
10359 
10360 	total_miss_count = nla_get_u8(attr);
10361 	ucfg_mlme_get_roam_bmiss_first_bcnt(hdd_ctx->psoc,
10362 					    &first_miss_count);
10363 	if (total_miss_count <= first_miss_count) {
10364 		hdd_err("Total %u needs to exceed first %u",
10365 			total_miss_count, first_miss_count);
10366 		return -EINVAL;
10367 	}
10368 
10369 	final_miss_count = total_miss_count - first_miss_count;
10370 
10371 	if (!ucfg_mlme_validate_roam_bmiss_final_bcnt(final_miss_count))
10372 		return -EINVAL;
10373 
10374 	hdd_debug("First count %u, final count %u",
10375 		  first_miss_count, final_miss_count);
10376 
10377 	status = sme_set_roam_bmiss_final_bcnt(hdd_ctx->mac_handle,
10378 					       link_info->vdev_id,
10379 					       final_miss_count);
10380 	if (QDF_IS_STATUS_ERROR(status)) {
10381 		hdd_err("Failed to set final count, status %u", status);
10382 		return qdf_status_to_os_return(status);
10383 	}
10384 
10385 	status = sme_set_bmiss_bcnt(link_info->vdev_id,
10386 				    first_miss_count,
10387 				    final_miss_count);
10388 	if (QDF_IS_STATUS_ERROR(status))
10389 		hdd_err("Failed to set count, status %u", status);
10390 
10391 	return qdf_status_to_os_return(status);
10392 }
10393 
10394 #ifdef WLAN_FEATURE_LL_MODE
10395 static inline
10396 void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level)
10397 {
10398 	if (latency_level ==
10399 		QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW)
10400 		wlan_hdd_set_pm_qos_request(hdd_ctx, true);
10401 	else
10402 		wlan_hdd_set_pm_qos_request(hdd_ctx, false);
10403 }
10404 #else
10405 static inline
10406 void wlan_hdd_set_wlm_mode(struct hdd_context *hdd_ctx, uint16_t latency_level)
10407 {
10408 }
10409 #endif
10410 
10411 /**
10412  * hdd_set_wlm_host_latency_level() - set latency flags based on latency flags
10413  * @hdd_ctx: hdd context
10414  * @adapter: adapter context
10415  * @latency_host_flags: host latency flags
10416  *
10417  * Return: none
10418  */
10419 static void hdd_set_wlm_host_latency_level(struct hdd_context *hdd_ctx,
10420 					   struct hdd_adapter *adapter,
10421 					   uint32_t latency_host_flags)
10422 {
10423 	ol_txrx_soc_handle soc_hdl = cds_get_context(QDF_MODULE_ID_SOC);
10424 	struct wlan_objmgr_vdev *vdev;
10425 
10426 	if (!soc_hdl)
10427 		return;
10428 
10429 	if (latency_host_flags & WLM_HOST_PM_QOS_FLAG) {
10430 		hdd_ctx->pm_qos_request_flags |=
10431 					(1 << adapter->deflink->vdev_id);
10432 	} else {
10433 		hdd_ctx->pm_qos_request_flags &=
10434 					~(1 << adapter->deflink->vdev_id);
10435 	}
10436 
10437 	if (hdd_ctx->pm_qos_request_flags)
10438 		wlan_hdd_set_pm_qos_request(hdd_ctx, true);
10439 	else
10440 		wlan_hdd_set_pm_qos_request(hdd_ctx, false);
10441 
10442 	if (latency_host_flags & WLM_HOST_HBB_FLAG)
10443 		ucfg_dp_set_high_bus_bw_request(hdd_ctx->psoc,
10444 						adapter->deflink->vdev_id,
10445 						true);
10446 	else
10447 		ucfg_dp_set_high_bus_bw_request(hdd_ctx->psoc,
10448 						adapter->deflink->vdev_id,
10449 						false);
10450 
10451 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
10452 	if (!vdev)
10453 		return;
10454 
10455 	if (latency_host_flags & WLM_HOST_RX_THREAD_FLAG)
10456 		ucfg_dp_runtime_disable_rx_thread(vdev, true);
10457 	else
10458 		ucfg_dp_runtime_disable_rx_thread(vdev, false);
10459 
10460 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
10461 }
10462 
10463 #ifdef MULTI_CLIENT_LL_SUPPORT
10464 void
10465 hdd_latency_level_event_handler_cb(const struct latency_level_data *event_data,
10466 				   uint8_t vdev_id)
10467 {
10468 	struct osif_request *request;
10469 	struct latency_level_data *data;
10470 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10471 	struct hdd_adapter *hdd_adapter;
10472 	uint32_t latency_host_flags = 0;
10473 	QDF_STATUS status;
10474 	struct wlan_hdd_link_info *link_info;
10475 
10476 	hdd_enter();
10477 
10478 	if (wlan_hdd_validate_context(hdd_ctx))
10479 		return;
10480 
10481 	if (!event_data) {
10482 		hdd_err("Invalid latency level event data");
10483 		return;
10484 	}
10485 
10486 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
10487 	if (!link_info) {
10488 		hdd_err("adapter is NULL vdev_id = %d", vdev_id);
10489 		return;
10490 	}
10491 
10492 	hdd_adapter = link_info->adapter;
10493 	if (hdd_adapter->multi_ll_resp_expected) {
10494 		request =
10495 			osif_request_get(hdd_adapter->multi_ll_response_cookie);
10496 		if (!request) {
10497 			hdd_err("Invalid request");
10498 			return;
10499 		}
10500 		data = osif_request_priv(request);
10501 		data->latency_level = event_data->latency_level;
10502 		data->vdev_id = event_data->vdev_id;
10503 		osif_request_complete(request);
10504 		osif_request_put(request);
10505 	} else {
10506 		hdd_adapter->latency_level = event_data->latency_level;
10507 		wlan_hdd_set_wlm_mode(hdd_ctx, hdd_adapter->latency_level);
10508 		hdd_debug("adapter->latency_level:%d",
10509 			  hdd_adapter->latency_level);
10510 		status = ucfg_mlme_get_latency_host_flags(hdd_ctx->psoc,
10511 						hdd_adapter->latency_level,
10512 						&latency_host_flags);
10513 		if (QDF_IS_STATUS_ERROR(status))
10514 			hdd_err("failed to get latency host flags");
10515 		else
10516 			hdd_set_wlm_host_latency_level(hdd_ctx, hdd_adapter,
10517 						       latency_host_flags);
10518 		}
10519 
10520 	hdd_exit();
10521 }
10522 
10523 uint8_t wlan_hdd_get_client_id_bitmap(struct hdd_adapter *adapter)
10524 {
10525 	uint8_t i, client_id_bitmap = 0;
10526 
10527 	for (i = 0; i < WLM_MAX_HOST_CLIENT; i++) {
10528 		if (!adapter->client_info[i].in_use)
10529 			continue;
10530 		client_id_bitmap |=
10531 			BIT(adapter->client_info[i].client_id);
10532 	}
10533 
10534 	return client_id_bitmap;
10535 }
10536 
10537 QDF_STATUS wlan_hdd_get_set_client_info_id(struct hdd_adapter *adapter,
10538 					   uint32_t port_id,
10539 					   uint32_t *client_id)
10540 {
10541 	uint8_t i;
10542 	QDF_STATUS status = QDF_STATUS_E_INVAL;
10543 
10544 	for (i = 0; i < WLM_MAX_HOST_CLIENT; i++) {
10545 		if (adapter->client_info[i].in_use) {
10546 			/* Receives set latency cmd for an existing port id */
10547 			if (port_id == adapter->client_info[i].port_id) {
10548 				*client_id = adapter->client_info[i].client_id;
10549 				status = QDF_STATUS_SUCCESS;
10550 				break;
10551 			}
10552 			continue;
10553 		} else {
10554 			/* Process set latency level from a new client */
10555 			adapter->client_info[i].in_use = true;
10556 			adapter->client_info[i].port_id = port_id;
10557 			*client_id = adapter->client_info[i].client_id;
10558 			status = QDF_STATUS_SUCCESS;
10559 			break;
10560 		}
10561 	}
10562 
10563 	if (i == WLM_MAX_HOST_CLIENT)
10564 		hdd_debug("Max client ID reached");
10565 
10566 	return status;
10567 }
10568 
10569 QDF_STATUS wlan_hdd_set_wlm_latency_level(struct hdd_adapter *adapter,
10570 					  uint16_t latency_level,
10571 					  uint32_t client_id_bitmap,
10572 					  bool force_reset)
10573 {
10574 	QDF_STATUS status;
10575 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10576 	int ret;
10577 	struct osif_request *request = NULL;
10578 	struct latency_level_data *priv;
10579 	static const struct osif_request_params params = {
10580 		.priv_size = sizeof(*priv),
10581 		.timeout_ms = WLAN_WAIT_WLM_LATENCY_LEVEL,
10582 		.dealloc = NULL,
10583 	};
10584 
10585 	/* ignore unless in STA mode */
10586 	if (adapter->device_mode != QDF_STA_MODE) {
10587 		hdd_debug_rl("WLM offload is supported in STA mode only");
10588 		return QDF_STATUS_E_FAILURE;
10589 	}
10590 
10591 	adapter->multi_ll_resp_expected = true;
10592 
10593 	request = osif_request_alloc(&params);
10594 	if (!request) {
10595 		hdd_err("Request allocation failure");
10596 		return QDF_STATUS_E_FAILURE;
10597 	}
10598 	adapter->multi_ll_response_cookie = osif_request_cookie(request);
10599 	adapter->multi_ll_req_in_progress = true;
10600 
10601 	status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
10602 					   adapter->deflink->vdev_id,
10603 					   latency_level, client_id_bitmap,
10604 					   force_reset);
10605 	if (QDF_IS_STATUS_ERROR(status)) {
10606 		hdd_err("Failure while sending command to fw");
10607 		goto err;
10608 	}
10609 
10610 	ret = osif_request_wait_for_response(request);
10611 	if (ret) {
10612 		hdd_err("SME timed out while retrieving latency level");
10613 		status = qdf_status_from_os_return(ret);
10614 		goto err;
10615 	}
10616 	priv = osif_request_priv(request);
10617 	if (!priv) {
10618 		hdd_err("invalid get latency level");
10619 		status = QDF_STATUS_E_FAILURE;
10620 		goto err;
10621 	}
10622 
10623 	hdd_debug("latency level received from FW:%d", priv->latency_level);
10624 	adapter->latency_level = priv->latency_level;
10625 err:
10626 	if (request)
10627 		osif_request_put(request);
10628 	adapter->multi_ll_req_in_progress = false;
10629 	adapter->multi_ll_resp_expected = false;
10630 	adapter->multi_ll_response_cookie = NULL;
10631 
10632 	return status;
10633 }
10634 
10635 bool hdd_get_multi_client_ll_support(struct hdd_adapter *adapter)
10636 {
10637 	return adapter->multi_client_ll_support;
10638 }
10639 
10640 /**
10641  * wlan_hdd_reset_client_info() - reset multi client info table
10642  * @adapter: adapter context
10643  * @client_id: client id
10644  *
10645  * Return: none
10646  */
10647 static void wlan_hdd_reset_client_info(struct hdd_adapter *adapter,
10648 				       uint32_t client_id)
10649 {
10650 	adapter->client_info[client_id].in_use = false;
10651 	adapter->client_info[client_id].port_id = 0;
10652 	adapter->client_info[client_id].client_id = client_id;
10653 }
10654 
10655 QDF_STATUS wlan_hdd_set_wlm_client_latency_level(struct hdd_adapter *adapter,
10656 						 uint32_t port_id,
10657 						 uint16_t latency_level)
10658 {
10659 	uint32_t client_id, client_id_bitmap;
10660 	QDF_STATUS status;
10661 
10662 	status = wlan_hdd_get_set_client_info_id(adapter, port_id,
10663 						 &client_id);
10664 	if (QDF_IS_STATUS_ERROR(status))
10665 		return status;
10666 
10667 	client_id_bitmap = BIT(client_id);
10668 	status = wlan_hdd_set_wlm_latency_level(adapter,
10669 						latency_level,
10670 						client_id_bitmap,
10671 						false);
10672 	if (QDF_IS_STATUS_ERROR(status)) {
10673 		hdd_debug("Fail to set latency level for client_id:%d",
10674 			  client_id);
10675 		wlan_hdd_reset_client_info(adapter, client_id);
10676 		return status;
10677 	}
10678 	return status;
10679 }
10680 
10681 /**
10682  * wlan_hdd_get_multi_ll_req_in_progress() - get multi_ll_req_in_progress flag
10683  * @adapter: adapter context
10684  *
10685  * Return: true if multi ll req in progress
10686  */
10687 static bool wlan_hdd_get_multi_ll_req_in_progress(struct hdd_adapter *adapter)
10688 {
10689 	return adapter->multi_ll_req_in_progress;
10690 }
10691 #else
10692 static inline bool
10693 wlan_hdd_get_multi_ll_req_in_progress(struct hdd_adapter *adapter)
10694 {
10695 	return false;
10696 }
10697 #endif
10698 
10699 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
10700 static QDF_STATUS hdd_get_netlink_sender_portid(struct hdd_context *hdd_ctx,
10701 						uint32_t *port_id)
10702 {
10703 	struct wiphy *wiphy = hdd_ctx->wiphy;
10704 
10705 	/* get netlink portid of sender */
10706 	*port_id =  cfg80211_vendor_cmd_get_sender(wiphy);
10707 
10708 	return QDF_STATUS_SUCCESS;
10709 }
10710 #else
10711 static inline QDF_STATUS
10712 hdd_get_netlink_sender_portid(struct hdd_context *hdd_ctx, uint32_t *port_id)
10713 {
10714 	return QDF_STATUS_E_NOSUPPORT;
10715 }
10716 #endif
10717 
10718 static int hdd_config_latency_level(struct wlan_hdd_link_info *link_info,
10719 				    const struct nlattr *attr)
10720 {
10721 	struct hdd_adapter *adapter = link_info->adapter;
10722 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10723 	uint32_t port_id;
10724 	uint16_t latency_level, host_latency_level;
10725 	QDF_STATUS status;
10726 	uint32_t latency_host_flags = 0;
10727 	int ret;
10728 
10729 	if (hdd_validate_adapter(adapter))
10730 		return -EINVAL;
10731 
10732 	if (!hdd_is_wlm_latency_manager_supported(hdd_ctx))
10733 		return -ENOTSUPP;
10734 
10735 	latency_level = nla_get_u16(attr);
10736 	switch (latency_level) {
10737 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL:
10738 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_XR:
10739 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW:
10740 	case QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW:
10741 		/* valid values */
10742 		break;
10743 	default:
10744 		hdd_err("Invalid value %u", latency_level);
10745 		return -EINVAL;
10746 	}
10747 
10748 	host_latency_level = latency_level - 1;
10749 
10750 	if (hdd_get_multi_client_ll_support(adapter)) {
10751 		if (wlan_hdd_get_multi_ll_req_in_progress(adapter)) {
10752 			hdd_err_rl("multi ll request already in progress");
10753 			return -EBUSY;
10754 		}
10755 		/* get netlink portid of sender */
10756 		status = hdd_get_netlink_sender_portid(hdd_ctx, &port_id);
10757 		if (QDF_IS_STATUS_ERROR(status))
10758 			goto error;
10759 		status = wlan_hdd_set_wlm_client_latency_level(adapter, port_id,
10760 							host_latency_level);
10761 		if (QDF_IS_STATUS_ERROR(status)) {
10762 			hdd_debug("Fail to set latency level");
10763 			goto error;
10764 		}
10765 	} else {
10766 		status = sme_set_wlm_latency_level(hdd_ctx->mac_handle,
10767 						   link_info->vdev_id,
10768 						   host_latency_level, 0,
10769 						   false);
10770 		if (QDF_IS_STATUS_ERROR(status)) {
10771 			hdd_err("set latency level failed, %u", status);
10772 			goto error;
10773 		}
10774 		adapter->latency_level = host_latency_level;
10775 	}
10776 
10777 	wlan_hdd_set_wlm_mode(hdd_ctx, adapter->latency_level);
10778 	hdd_debug("adapter->latency_level:%d", adapter->latency_level);
10779 
10780 	status = ucfg_mlme_get_latency_host_flags(hdd_ctx->psoc,
10781 						  adapter->latency_level,
10782 						  &latency_host_flags);
10783 	if (QDF_IS_STATUS_ERROR(status))
10784 		hdd_err("failed to get latency host flags");
10785 	else
10786 		hdd_set_wlm_host_latency_level(hdd_ctx, adapter,
10787 					       latency_host_flags);
10788 error:
10789 	ret = qdf_status_to_os_return(status);
10790 
10791 	return ret;
10792 }
10793 
10794 static int hdd_config_disable_fils(struct wlan_hdd_link_info *link_info,
10795 				   const struct nlattr *attr)
10796 {
10797 	struct hdd_adapter *adapter = link_info->adapter;
10798 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10799 	uint8_t disable_fils;
10800 	bool enabled;
10801 	QDF_STATUS status;
10802 
10803 	/* ignore unless in STA mode */
10804 	if (adapter->device_mode != QDF_STA_MODE)
10805 		return 0;
10806 
10807 	disable_fils = nla_get_u8(attr);
10808 	hdd_debug("%u", disable_fils);
10809 
10810 	enabled = !disable_fils;
10811 	status = ucfg_mlme_set_fils_enabled_info(hdd_ctx->psoc, enabled);
10812 	if (QDF_IS_STATUS_ERROR(status))
10813 		hdd_err("could not set fils enabled info, %d", status);
10814 
10815 	status = ucfg_mlme_set_enable_bcast_probe_rsp(hdd_ctx->psoc, enabled);
10816 	if (QDF_IS_STATUS_ERROR(status))
10817 		hdd_err("could not set enable bcast probe resp info, %d",
10818 			status);
10819 
10820 	status = wma_cli_set_command(link_info->vdev_id,
10821 				     wmi_vdev_param_enable_bcast_probe_response,
10822 				     !disable_fils, VDEV_CMD);
10823 	if (QDF_IS_STATUS_ERROR(status))
10824 		hdd_err("failed to set enable bcast probe resp, %d",
10825 			status);
10826 
10827 	return qdf_status_to_os_return(status);
10828 }
10829 
10830 static int hdd_set_primary_interface(struct wlan_hdd_link_info *link_info,
10831 				     const struct nlattr *attr)
10832 {
10833 	struct hdd_adapter *adapter = link_info->adapter;
10834 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10835 	bool is_set_primary_iface;
10836 	QDF_STATUS status;
10837 	uint8_t vdev_id,  primary_vdev_id, dual_sta_policy;
10838 	int set_value;
10839 	uint32_t count;
10840 	bool enable_mcc_adaptive_sch = false;
10841 
10842 	/* ignore unless in STA mode */
10843 	if (adapter->device_mode != QDF_STA_MODE)
10844 		return 0;
10845 
10846 	is_set_primary_iface = nla_get_u8(attr);
10847 
10848 	vdev_id = link_info->vdev_id;
10849 	primary_vdev_id =
10850 		is_set_primary_iface ? vdev_id : WLAN_UMAC_VDEV_ID_MAX;
10851 
10852 	status = ucfg_mlme_set_primary_interface(hdd_ctx->psoc,
10853 						 primary_vdev_id);
10854 	if (QDF_IS_STATUS_ERROR(status)) {
10855 		hdd_err("could not set primary interface, %d", status);
10856 		return -EINVAL;
10857 	}
10858 
10859 	/* After SSR, the dual sta configuration is lost. As SSR is hidden from
10860 	 * userland, this command will not come from userspace after a SSR. To
10861 	 * restore this configuration, save this in hdd context and restore
10862 	 * after re-init.
10863 	 */
10864 	hdd_ctx->dual_sta_policy.primary_vdev_id = primary_vdev_id;
10865 
10866 	count = policy_mgr_mode_specific_connection_count(hdd_ctx->psoc,
10867 							  PM_STA_MODE, NULL);
10868 
10869 	if (count < 2) {
10870 		hdd_debug("STA + STA concurrency not present, count:%d", count);
10871 		return 0;
10872 	}
10873 
10874 	/* If dual sta roaming enabled and sta concurrency on different mac then
10875 	 * no need to enable roaming on primary as both STA's have roaming
10876 	 * enabled.
10877 	 * If dual sta roaming enabled and both sta in MCC or SCC then need
10878 	 * to enable roaming on primary vdev.
10879 	 * If dual sta roaming NOT enabled then need to enable roaming on
10880 	 * primary vdev for sta concurrency on different mac.
10881 	 */
10882 	if (wlan_mlme_is_primary_interface_configured(hdd_ctx->psoc))
10883 		if ((ucfg_mlme_get_dual_sta_roaming_enabled(hdd_ctx->psoc) &&
10884 		     !policy_mgr_concurrent_sta_on_different_mac(hdd_ctx->psoc)) ||
10885 		    !ucfg_mlme_get_dual_sta_roaming_enabled(hdd_ctx->psoc)) {
10886 			hdd_err("Enable roaming on requested interface: %d",
10887 				link_info->vdev_id);
10888 			hdd_debug("Enable roaming on requested interface: %d",
10889 				  link_info->vdev_id);
10890 			wlan_cm_roam_state_change(hdd_ctx->pdev,
10891 						  link_info->vdev_id,
10892 						  WLAN_ROAM_RSO_ENABLED,
10893 						  REASON_ROAM_SET_PRIMARY);
10894 	}
10895 
10896 	/*
10897 	 * send duty cycle percentage to FW only if STA + STA
10898 	 * concurrency is in MCC.
10899 	 */
10900 	if (!policy_mgr_current_concurrency_is_mcc(hdd_ctx->psoc)) {
10901 		hdd_debug("STA + STA concurrency not in MCC");
10902 		return 0;
10903 	}
10904 
10905 	status = ucfg_mlme_get_dual_sta_policy(hdd_ctx->psoc, &dual_sta_policy);
10906 	if (QDF_IS_STATUS_ERROR(status)) {
10907 		hdd_err("could not get dual sta policy, %d", status);
10908 		return -EINVAL;
10909 	}
10910 
10911 	hdd_debug("is_set_primary_iface: %d, primary vdev id: %d, dual_sta_policy:%d",
10912 		  is_set_primary_iface, primary_vdev_id, dual_sta_policy);
10913 
10914 	if (is_set_primary_iface && dual_sta_policy ==
10915 	    QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY) {
10916 		hdd_debug("Disable mcc_adaptive_scheduler");
10917 		ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc,
10918 						     &enable_mcc_adaptive_sch);
10919 		if (enable_mcc_adaptive_sch) {
10920 			ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch(
10921 							hdd_ctx->psoc, false);
10922 			if (QDF_IS_STATUS_ERROR(sme_set_mas(false))) {
10923 				hdd_err("Fail to disable mcc adaptive sched.");
10924 					return -EINVAL;
10925 			}
10926 		}
10927 		/* Configure mcc duty cycle percentage */
10928 		set_value =
10929 		   ucfg_mlme_get_mcc_duty_cycle_percentage(hdd_ctx->pdev);
10930 		if (set_value < 0) {
10931 			hdd_err("Invalid mcc duty cycle");
10932 			return -EINVAL;
10933 		}
10934 		wlan_hdd_send_mcc_vdev_quota(adapter, set_value);
10935 	} else {
10936 		hdd_debug("Enable mcc_adaptive_scheduler");
10937 		ucfg_policy_mgr_get_mcc_adaptive_sch(hdd_ctx->psoc,
10938 						     &enable_mcc_adaptive_sch);
10939 		if (enable_mcc_adaptive_sch) {
10940 			ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch(
10941 							hdd_ctx->psoc, true);
10942 			if (QDF_STATUS_SUCCESS != sme_set_mas(true)) {
10943 				hdd_err("Fail to enable mcc_adaptive_sched.");
10944 				return -EAGAIN;
10945 			}
10946 		}
10947 	}
10948 
10949 	return 0;
10950 }
10951 
10952 static int hdd_config_rsn_ie(struct wlan_hdd_link_info *link_info,
10953 			     const struct nlattr *attr)
10954 {
10955 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
10956 	uint8_t force_rsne_override;
10957 
10958 	force_rsne_override = nla_get_u8(attr);
10959 	if (force_rsne_override > 1) {
10960 		hdd_err("Invalid value %d", force_rsne_override);
10961 		return -EINVAL;
10962 	}
10963 
10964 	hdd_ctx->force_rsne_override = force_rsne_override;
10965 	hdd_debug("force_rsne_override - %d", force_rsne_override);
10966 
10967 	return 0;
10968 }
10969 
10970 static int hdd_config_gtx(struct wlan_hdd_link_info *link_info,
10971 			  const struct nlattr *attr)
10972 {
10973 	uint8_t config_gtx;
10974 	int errno;
10975 
10976 	config_gtx = nla_get_u8(attr);
10977 	if (config_gtx > 1) {
10978 		hdd_err_rl("Invalid config_gtx value %d", config_gtx);
10979 		return -EINVAL;
10980 	}
10981 
10982 	errno = sme_cli_set_command(link_info->vdev_id,
10983 				    wmi_vdev_param_gtx_enable,
10984 				    config_gtx, VDEV_CMD);
10985 	if (errno)
10986 		hdd_err("Failed to set GTX, %d", errno);
10987 
10988 	return errno;
10989 }
10990 
10991 /**
10992  * hdd_config_disconnect_ies() - Configure disconnect IEs
10993  * @link_info: Link info pointer in HDD adapter
10994  * @attr: array of pointer to struct nlattr
10995  *
10996  * Return: 0 on success; error number otherwise
10997  */
10998 static int hdd_config_disconnect_ies(struct wlan_hdd_link_info *link_info,
10999 				     const struct nlattr *attr)
11000 {
11001 	struct hdd_adapter *adapter = link_info->adapter;
11002 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11003 	QDF_STATUS status;
11004 
11005 	hdd_debug("IE len %u session %u device mode %u",
11006 		  nla_len(attr), link_info->vdev_id,
11007 		  adapter->device_mode);
11008 	if (!nla_len(attr) ||
11009 	    nla_len(attr) > SIR_MAC_MAX_ADD_IE_LENGTH + 2 ||
11010 	    !wlan_is_ie_valid(nla_data(attr), nla_len(attr))) {
11011 		hdd_err("Invalid disconnect IEs");
11012 		return -EINVAL;
11013 	}
11014 
11015 	status = sme_set_disconnect_ies(hdd_ctx->mac_handle,
11016 					link_info->vdev_id,
11017 					nla_data(attr),
11018 					nla_len(attr));
11019 	if (QDF_IS_STATUS_ERROR(status))
11020 		hdd_err("Failed to set disconnect_ies");
11021 
11022 	return qdf_status_to_os_return(status);
11023 }
11024 
11025 #ifdef WLAN_FEATURE_ELNA
11026 /**
11027  * hdd_set_elna_bypass() - Set eLNA bypass
11028  * @link_info: Link info pointer in HDD adapter
11029  * @attr: Pointer to struct nlattr
11030  *
11031  * Return: 0 on success; error number otherwise
11032  */
11033 static int hdd_set_elna_bypass(struct wlan_hdd_link_info *link_info,
11034 			       const struct nlattr *attr)
11035 {
11036 	int ret;
11037 	struct wlan_objmgr_vdev *vdev;
11038 
11039 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_FWOL_NB_ID);
11040 	if (!vdev)
11041 		return -EINVAL;
11042 
11043 	ret = os_if_fwol_set_elna_bypass(vdev, attr);
11044 
11045 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_FWOL_NB_ID);
11046 
11047 	return ret;
11048 }
11049 #endif
11050 
11051 /**
11052  * hdd_mac_chwidth_to_bonding_mode() - get bonding_mode from chan width
11053  * @chwidth: chan width
11054  *
11055  * Return: bonding mode
11056  */
11057 static uint32_t hdd_mac_chwidth_to_bonding_mode(
11058 			enum eSirMacHTChannelWidth chwidth)
11059 {
11060 	uint32_t bonding_mode;
11061 
11062 	switch (chwidth) {
11063 	case eHT_CHANNEL_WIDTH_20MHZ:
11064 		bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
11065 		break;
11066 	default:
11067 		bonding_mode = WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
11068 	}
11069 
11070 	return bonding_mode;
11071 }
11072 
11073 int hdd_set_mac_chan_width(struct wlan_hdd_link_info *link_info,
11074 			   enum eSirMacHTChannelWidth chwidth,
11075 			   uint8_t link_id, bool is_restore)
11076 {
11077 	uint32_t bonding_mode;
11078 
11079 	bonding_mode = hdd_mac_chwidth_to_bonding_mode(chwidth);
11080 
11081 	return hdd_update_channel_width(link_info, chwidth,
11082 					bonding_mode, link_id, is_restore);
11083 }
11084 
11085 /**
11086  * hdd_set_channel_width() - set channel width
11087  * @link_info: Link info pointer in HDD adapter.
11088  * @tb: array of pointer to struct nlattr
11089  *
11090  * Return: 0 on success, negative errno on failure
11091  */
11092 static int hdd_set_channel_width(struct wlan_hdd_link_info *link_info,
11093 				 struct nlattr *tb[])
11094 {
11095 	int rem;
11096 	uint8_t nl80211_chwidth = 0xFF;
11097 	uint8_t link_id = 0xFF;
11098 	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
11099 	struct nlattr *curr_attr;
11100 	struct nlattr *chn_bd = NULL;
11101 	struct nlattr *mlo_link_id;
11102 	enum eSirMacHTChannelWidth chwidth;
11103 	struct wlan_objmgr_psoc *psoc;
11104 	bool update_cw_allowed;
11105 
11106 	psoc = wlan_vdev_get_psoc(link_info->vdev);
11107 	if (!psoc) {
11108 		hdd_debug("psoc is null");
11109 		return -EINVAL;
11110 	}
11111 
11112 	ucfg_mlme_get_update_chan_width_allowed(psoc, &update_cw_allowed);
11113 	if (!update_cw_allowed) {
11114 		hdd_debug("update_channel_width is disabled via INI");
11115 		return -EINVAL;
11116 	}
11117 
11118 	if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS])
11119 		goto skip_mlo;
11120 
11121 	nla_for_each_nested(curr_attr,
11122 			    tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS], rem) {
11123 		if (wlan_cfg80211_nla_parse_nested(tb2,
11124 						QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
11125 						   curr_attr,
11126 						   bandwidth_mlo_policy)){
11127 			hdd_err_rl("nla_parse failed");
11128 			return -EINVAL;
11129 		}
11130 
11131 		chn_bd = tb2[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH];
11132 		mlo_link_id = tb2[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINK_ID];
11133 
11134 		if (!chn_bd || !mlo_link_id)
11135 			return -EINVAL;
11136 
11137 		nl80211_chwidth = nla_get_u8(chn_bd);
11138 		chwidth = hdd_nl80211_chwidth_to_chwidth(nl80211_chwidth);
11139 		if (chwidth < eHT_CHANNEL_WIDTH_20MHZ ||
11140 		    chwidth >= eHT_MAX_CHANNEL_WIDTH) {
11141 			hdd_err("Invalid channel width:%u", chwidth);
11142 			return -EINVAL;
11143 		}
11144 
11145 		link_id = nla_get_u8(mlo_link_id);
11146 		if (link_id > WLAN_MAX_LINK_ID) {
11147 			hdd_debug("invalid link_id:%u", link_id);
11148 			return -EINVAL;
11149 		}
11150 	}
11151 
11152 	if (link_id != 0xFF)
11153 		goto set_chan_width;
11154 
11155 skip_mlo:
11156 	chn_bd = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH];
11157 
11158 	if (!chn_bd)
11159 		return 0;
11160 
11161 	nl80211_chwidth = nla_get_u8(chn_bd);
11162 	chwidth = hdd_nl80211_chwidth_to_chwidth(nl80211_chwidth);
11163 
11164 	if (chwidth < eHT_CHANNEL_WIDTH_20MHZ ||
11165 	    chwidth >= eHT_MAX_CHANNEL_WIDTH) {
11166 		hdd_err("Invalid channel width %u", chwidth);
11167 		return -EINVAL;
11168 	}
11169 set_chan_width:
11170 	return hdd_set_mac_chan_width(link_info, chwidth, link_id, true);
11171 }
11172 
11173 /**
11174  * hdd_set_dynamic_bw() - enable / disable dynamic bandwidth
11175  * @link_info: Link info in adapter
11176  * @attr: nla attr sent by supplicant
11177  *
11178  * Return: 0 on success, negative errno on failure
11179  */
11180 static int hdd_set_dynamic_bw(struct wlan_hdd_link_info *link_info,
11181 			      const struct nlattr *attr)
11182 {
11183 	uint8_t enable;
11184 
11185 	enable = nla_get_u8(attr);
11186 	return wma_cli_set_command(link_info->vdev_id,
11187 				   wmi_pdev_param_dynamic_bw,
11188 				   enable, PDEV_CMD);
11189 }
11190 
11191 /**
11192  * hdd_set_nss() - set the number of spatial streams supported by the adapter
11193  * @link_info: Link info pointer in HDD adapter
11194  * @attr: pointer to nla attr
11195  *
11196  * Return: 0 on success, negative errno on failure
11197  */
11198 static int hdd_set_nss(struct wlan_hdd_link_info *link_info,
11199 		       const struct nlattr *attr)
11200 {
11201 	uint8_t nss;
11202 	int ret;
11203 	QDF_STATUS status;
11204 
11205 	nss = nla_get_u8(attr);
11206 	status = hdd_update_nss(link_info, nss, nss);
11207 	ret = qdf_status_to_os_return(status);
11208 
11209 	if (ret == 0 && link_info->adapter->device_mode == QDF_SAP_MODE)
11210 		ret = wma_cli_set_command(link_info->vdev_id,
11211 					  wmi_vdev_param_nss, nss, VDEV_CMD);
11212 
11213 	return ret;
11214 }
11215 
11216 #ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD
11217 #define DYNAMIC_ARP_NS_ENABLE    1
11218 #define DYNAMIC_ARP_NS_DISABLE   0
11219 
11220 /**
11221  * hdd_set_arp_ns_offload() - enable/disable arp/ns offload feature
11222  * @link_info: Link info pointer in HDD adapter
11223  * @attr: pointer to nla attr
11224  *
11225  * Return: 0 on success, negative errno on failure
11226  */
11227 static int hdd_set_arp_ns_offload(struct wlan_hdd_link_info *link_info,
11228 				  const struct nlattr *attr)
11229 {
11230 	uint8_t offload_state;
11231 	int errno;
11232 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
11233 	struct hdd_adapter *adapter = link_info->adapter;
11234 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11235 	struct wlan_objmgr_vdev *vdev;
11236 
11237 	errno = wlan_hdd_validate_context(hdd_ctx);
11238 	if (errno)
11239 		return errno;
11240 
11241 	if (!ucfg_pmo_is_arp_offload_enabled(hdd_ctx->psoc) ||
11242 	    !ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
11243 		hdd_err_rl("ARP/NS Offload is disabled by ini");
11244 		return -EINVAL;
11245 	}
11246 
11247 	if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
11248 		hdd_err_rl("active mode offload is disabled by ini");
11249 		return -EINVAL;
11250 	}
11251 
11252 	if (adapter->device_mode != QDF_STA_MODE &&
11253 	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
11254 		hdd_err_rl("only support on sta/p2p-cli mode");
11255 		return -EINVAL;
11256 	}
11257 
11258 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
11259 	if (!vdev) {
11260 		hdd_err("vdev is NULL");
11261 		return -EINVAL;
11262 	}
11263 
11264 	offload_state = nla_get_u8(attr);
11265 
11266 	if (offload_state == DYNAMIC_ARP_NS_ENABLE)
11267 		qdf_status = ucfg_pmo_dynamic_arp_ns_offload_enable(vdev);
11268 	else if (offload_state == DYNAMIC_ARP_NS_DISABLE)
11269 		qdf_status = ucfg_pmo_dynamic_arp_ns_offload_disable(vdev);
11270 
11271 	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
11272 		if (offload_state == DYNAMIC_ARP_NS_ENABLE)
11273 			ucfg_pmo_dynamic_arp_ns_offload_runtime_allow(vdev);
11274 		else
11275 			ucfg_pmo_dynamic_arp_ns_offload_runtime_prevent(vdev);
11276 	}
11277 
11278 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
11279 		if (qdf_status == QDF_STATUS_E_ALREADY) {
11280 			hdd_info_rl("already set arp/ns offload %d",
11281 				    offload_state);
11282 			errno = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
11283 		} else {
11284 			errno = qdf_status_to_os_return(qdf_status);
11285 		}
11286 
11287 		goto vdev_ref;
11288 	}
11289 
11290 	if (!hdd_is_vdev_in_conn_state(link_info)) {
11291 		hdd_info("set not in connect state, updated state %d",
11292 			 offload_state);
11293 		errno = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
11294 		goto vdev_ref;
11295 	}
11296 
11297 	if (offload_state == DYNAMIC_ARP_NS_ENABLE) {
11298 		hdd_enable_arp_offload(adapter, vdev,
11299 				       pmo_arp_ns_offload_dynamic_update);
11300 		hdd_enable_ns_offload(adapter, vdev,
11301 				      pmo_arp_ns_offload_dynamic_update);
11302 	} else if (offload_state == DYNAMIC_ARP_NS_DISABLE) {
11303 		hdd_disable_arp_offload(adapter, vdev,
11304 					pmo_arp_ns_offload_dynamic_update);
11305 		hdd_disable_ns_offload(adapter, vdev,
11306 				       pmo_arp_ns_offload_dynamic_update);
11307 	}
11308 
11309 vdev_ref:
11310 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11311 	return errno;
11312 }
11313 
11314 #undef DYNAMIC_ARP_NS_ENABLE
11315 #undef DYNAMIC_ARP_NS_DISABLE
11316 #endif
11317 
11318 #ifdef WLAN_FEATURE_DBAM_CONFIG
11319 
11320 static int
11321 hdd_convert_qca_dbam_config_mode(enum qca_dbam_config qca_dbam,
11322 				 enum coex_dbam_config_mode *coex_dbam)
11323 {
11324 	switch (qca_dbam) {
11325 	case QCA_DBAM_DISABLE:
11326 		*coex_dbam = COEX_DBAM_DISABLE;
11327 		break;
11328 	case QCA_DBAM_ENABLE:
11329 		*coex_dbam = COEX_DBAM_ENABLE;
11330 		break;
11331 	case QCA_DBAM_FORCE_ENABLE:
11332 		*coex_dbam = COEX_DBAM_FORCE_ENABLE;
11333 		break;
11334 	default:
11335 		hdd_err("Invalid dbam config mode %d", qca_dbam);
11336 		return -EINVAL;
11337 	}
11338 
11339 	return 0;
11340 }
11341 
11342 static int
11343 hdd_convert_dbam_comp_status(enum coex_dbam_comp_status dbam_resp)
11344 {
11345 	switch (dbam_resp) {
11346 	case COEX_DBAM_COMP_SUCCESS:
11347 		return 0;
11348 	case COEX_DBAM_COMP_NOT_SUPPORT:
11349 		return -ENOTSUPP;
11350 	case COEX_DBAM_COMP_FAIL:
11351 		return -EINVAL;
11352 	default:
11353 		hdd_err("Invalid dbam config resp received from FW");
11354 		break;
11355 	}
11356 
11357 	return -EINVAL;
11358 }
11359 
11360 /**
11361  * hdd_dbam_config_resp_cb() - DBAM config response callback
11362  * @context: request manager context
11363  * @resp: pointer to dbam config fw response
11364  *
11365  * Return: 0 on success, negative errno on failure
11366  */
11367 static void
11368 hdd_dbam_config_resp_cb(void *context,
11369 			enum coex_dbam_comp_status *resp)
11370 {
11371 	struct osif_request *request;
11372 	struct coex_dbam_config_resp *priv;
11373 
11374 	request = osif_request_get(context);
11375 	if (!request) {
11376 		osif_err("Obsolete request");
11377 		return;
11378 	}
11379 
11380 	priv = osif_request_priv(request);
11381 	priv->dbam_resp = *resp;
11382 
11383 	osif_request_complete(request);
11384 	osif_request_put(request);
11385 }
11386 
11387 int hdd_send_dbam_config(struct hdd_adapter *adapter,
11388 			 enum coex_dbam_config_mode dbam_mode)
11389 {
11390 	int errno;
11391 	QDF_STATUS status;
11392 	struct wlan_objmgr_vdev *vdev;
11393 	enum coex_dbam_comp_status dbam_resp;
11394 	struct coex_dbam_config_params dbam_params = {0};
11395 	void *cookie;
11396 	struct osif_request *request;
11397 	struct coex_dbam_config_resp *priv;
11398 	static const struct osif_request_params params = {
11399 		.priv_size = sizeof(*priv),
11400 		.timeout_ms = WLAN_SET_DBAM_CONFIG_TIMEOUT,
11401 	};
11402 
11403 	errno = hdd_validate_adapter(adapter);
11404 	if (errno)
11405 		return errno;
11406 
11407 	request = osif_request_alloc(&params);
11408 	if (!request) {
11409 		osif_err("Request allocation failure");
11410 		return -ENOMEM;
11411 	}
11412 	cookie = osif_request_cookie(request);
11413 
11414 	dbam_params.vdev_id = adapter->deflink->vdev_id;
11415 	dbam_params.dbam_mode = dbam_mode;
11416 
11417 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
11418 	if (!vdev) {
11419 		hdd_err("vdev is NULL");
11420 		errno = -EINVAL;
11421 		goto err;
11422 	}
11423 
11424 	status = ucfg_coex_send_dbam_config(vdev, &dbam_params,
11425 					    hdd_dbam_config_resp_cb, cookie);
11426 
11427 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11428 
11429 	if (!QDF_IS_STATUS_SUCCESS(status)) {
11430 		hdd_err("Unable to set dbam config to [%u]", dbam_mode);
11431 		errno = qdf_status_to_os_return(status);
11432 		goto err;
11433 	}
11434 
11435 	errno = osif_request_wait_for_response(request);
11436 	if (errno) {
11437 		osif_err("DBAM config operation timed out");
11438 		goto err;
11439 	}
11440 
11441 	priv = osif_request_priv(request);
11442 	dbam_resp = priv->dbam_resp;
11443 	errno = hdd_convert_dbam_comp_status(dbam_resp);
11444 err:
11445 	osif_request_put(request);
11446 	return errno;
11447 }
11448 
11449 /**
11450  * hdd_set_dbam_config() - set DBAM config
11451  * @link_info: Link info pointer in HDD adapter
11452  * @attr: pointer to nla attr
11453  *
11454  * Return: 0 on success, negative errno on failure
11455  */
11456 static int hdd_set_dbam_config(struct wlan_hdd_link_info *link_info,
11457 			       const struct nlattr *attr)
11458 {
11459 	struct hdd_adapter *adapter = link_info->adapter;
11460 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11461 	int errno;
11462 	enum qca_dbam_config dbam_config;
11463 	enum coex_dbam_config_mode dbam_mode;
11464 
11465 	errno = wlan_hdd_validate_context(hdd_ctx);
11466 	if (errno)
11467 		return -EINVAL;
11468 
11469 	if (hdd_ctx->num_rf_chains < 2) {
11470 		hdd_debug("Num of chains [%u] < 2, DBAM config is not allowed",
11471 			  hdd_ctx->num_rf_chains);
11472 		return -EINVAL;
11473 	}
11474 
11475 	dbam_config = nla_get_u8(attr);
11476 	errno = hdd_convert_qca_dbam_config_mode(dbam_config, &dbam_mode);
11477 	if (errno)
11478 		return errno;
11479 
11480 	/* Store dbam config in hdd_ctx, to restore in case of an SSR */
11481 	adapter->is_dbam_configured = true;
11482 	hdd_ctx->dbam_mode = dbam_mode;
11483 
11484 	return hdd_send_dbam_config(adapter, dbam_mode);
11485 }
11486 #endif
11487 
11488 /**
11489  * hdd_set_beamformer_periodic_sounding() - enable/disable Tx Beamforming
11490  * @link_info: Link info pointer in HDD adapter
11491  * @attr: pointer to nla attr
11492  *
11493  * Return: 0 on success, negative on failure
11494  */
11495 static int
11496 hdd_set_beamformer_periodic_sounding(struct wlan_hdd_link_info *link_info,
11497 				     const struct nlattr *attr)
11498 {
11499 	uint8_t cfg_val;
11500 	int set_val;
11501 
11502 	cfg_val = nla_get_u8(attr);
11503 
11504 	set_val = cfg_val ? TX_BFER_NDP_PERIODICITY : 0;
11505 	return wma_cli_set_command(link_info->vdev_id,
11506 				   WMI_PDEV_PARAM_TXBF_SOUND_PERIOD_CMDID,
11507 				   set_val, PDEV_CMD);
11508 }
11509 
11510 /**
11511  * hdd_set_wfc_state() - Set wfc state
11512  * @link_info: Link info pointer in HDD adapter
11513  * @attr: pointer to nla attr
11514  *
11515  * Return: 0 on success, negative on failure
11516  */
11517 static int hdd_set_wfc_state(struct wlan_hdd_link_info *link_info,
11518 			     const struct nlattr *attr)
11519 {
11520 	uint8_t cfg_val;
11521 	enum pld_wfc_mode set_val;
11522 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11523 	int errno;
11524 
11525 	errno = wlan_hdd_validate_context(hdd_ctx);
11526 	if (errno)
11527 		return errno;
11528 
11529 	cfg_val = nla_get_u8(attr);
11530 
11531 	hdd_debug_rl("set wfc state %d", cfg_val);
11532 	if (cfg_val == 0)
11533 		set_val = PLD_WFC_MODE_OFF;
11534 	else if (cfg_val == 1)
11535 		set_val = PLD_WFC_MODE_ON;
11536 	else
11537 		return -EINVAL;
11538 
11539 	return pld_set_wfc_mode(hdd_ctx->parent_dev, set_val);
11540 
11541 }
11542 
11543 /**
11544  * hdd_set_ul_mu_config() - Configure UL MU i.e suspend/enable
11545  * @link_info: Link info pointer in HDD adapter
11546  * @attr: pointer to nla attr
11547  *
11548  * Return: 0 on success, negative on failure
11549  */
11550 
11551 static int hdd_set_ul_mu_config(struct wlan_hdd_link_info *link_info,
11552 				const struct nlattr *attr)
11553 {
11554 	uint8_t ulmu;
11555 	uint8_t ulmu_disable;
11556 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11557 	int errno;
11558 	QDF_STATUS qdf_status;
11559 
11560 	errno = wlan_hdd_validate_context(hdd_ctx);
11561 	if (errno) {
11562 		hdd_err("Invalid HDD ctx, errno : %d", errno);
11563 		return errno;
11564 	}
11565 
11566 	ulmu = nla_get_u8(attr);
11567 	if (ulmu != QCA_UL_MU_SUSPEND && ulmu != QCA_UL_MU_ENABLE) {
11568 		hdd_err("Invalid ulmu value, ulmu : %d", ulmu);
11569 		return -EINVAL;
11570 	}
11571 
11572 	hdd_debug("UL MU value : %d", ulmu);
11573 
11574 	if (ulmu == QCA_UL_MU_SUSPEND)
11575 		ulmu_disable = 1;
11576 	else
11577 		ulmu_disable = 0;
11578 
11579 	qdf_status = ucfg_mlme_set_ul_mu_config(hdd_ctx->psoc,
11580 						link_info->vdev_id,
11581 						ulmu_disable);
11582 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
11583 		errno = -EINVAL;
11584 		hdd_err("Failed to set UL MU, errno : %d", errno);
11585 	}
11586 
11587 	return errno;
11588 }
11589 
11590 /**
11591  * hdd_set_coex_traffic_shaping_mode() - Configure coex traffic
11592  * shaping mode
11593  * @link_info: Link info pointer in HDD adapter
11594  * @attr: pointer to nla attr
11595  *
11596  * Return: 0 on success, negative on failure
11597  */
11598 
11599 static int
11600 hdd_set_coex_traffic_shaping_mode(struct wlan_hdd_link_info *link_info,
11601 				  const struct nlattr *attr)
11602 {
11603 	uint8_t mode;
11604 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11605 	int errno, ret;
11606 
11607 	errno = wlan_hdd_validate_context(hdd_ctx);
11608 	if (errno) {
11609 		hdd_err("Invalid HDD ctx, errno : %d", errno);
11610 		return errno;
11611 	}
11612 
11613 	mode = nla_get_u8(attr);
11614 	if (mode > QCA_COEX_TRAFFIC_SHAPING_MODE_ENABLE) {
11615 		hdd_err("Invalid traffic shaping mode : %d", mode);
11616 		return -EINVAL;
11617 	}
11618 
11619 	hdd_debug("Coex Traffic shaping mode : %d", mode);
11620 
11621 	ret = hdd_send_coex_traffic_shaping_mode(link_info->vdev_id, mode);
11622 
11623 	return ret;
11624 }
11625 
11626 #ifdef WLAN_FEATURE_11BE_MLO
11627 static int hdd_test_config_emlsr_mode(struct hdd_context *hdd_ctx,
11628 				      bool cfg_val)
11629 
11630 {
11631 	hdd_debug("11be op mode setting %d", cfg_val);
11632 	if (cfg_val && policy_mgr_is_hw_emlsr_capable(hdd_ctx->psoc)) {
11633 		hdd_debug("HW supports EMLSR mode, set caps");
11634 		ucfg_mlme_set_emlsr_mode_enabled(hdd_ctx->psoc, cfg_val);
11635 	} else {
11636 		hdd_debug("Default mode: MLMR, no action required");
11637 	}
11638 
11639 	return 0;
11640 }
11641 
11642 static int
11643 hdd_test_config_emlsr_action_mode(struct hdd_adapter *adapter,
11644 				  enum wlan_emlsr_action_mode emlsr_mode)
11645 {
11646 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11647 	uint8_t i, num_links = 0;
11648 	uint16_t vdev_count = 0;
11649 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
11650 	struct qdf_mac_addr active_link_addr[2];
11651 
11652 	mlo_sta_get_vdev_list(adapter->deflink->vdev, &vdev_count,
11653 			      wlan_vdev_list);
11654 	for (i = 0; i < vdev_count; i++) {
11655 		if (!wlan_vdev_list[i])
11656 			continue;
11657 		qdf_mem_copy(&active_link_addr[i],
11658 			     wlan_vdev_mlme_get_macaddr(wlan_vdev_list[i]),
11659 			     QDF_MAC_ADDR_SIZE);
11660 		num_links++;
11661 		if (emlsr_mode == WLAN_EMLSR_MODE_EXIT)
11662 			break;
11663 	}
11664 
11665 	for (i = 0; i < vdev_count; i++)
11666 		mlo_release_vdev_ref(wlan_vdev_list[i]);
11667 
11668 	hdd_debug("number of links to force enable: %d", num_links);
11669 
11670 	if (num_links >= 1)
11671 		sme_activate_mlo_links(hdd_ctx->mac_handle,
11672 				       adapter->deflink->vdev_id,
11673 				       num_links, active_link_addr);
11674 
11675 	return 0;
11676 }
11677 
11678 /**
11679  * hdd_set_epcs_capability() - Set EPCS capability enable or not
11680  * @link_info: link info pointer
11681  * @attr: pointer to nla attr
11682  *
11683  * Return: 0 on success, negative on failure
11684  */
11685 static int hdd_set_epcs_capability(struct wlan_hdd_link_info *link_info,
11686 				   const struct nlattr *attr)
11687 {
11688 	uint8_t cfg_val;
11689 	struct wlan_objmgr_vdev *vdev;
11690 
11691 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
11692 	if (!vdev)
11693 		return -EINVAL;
11694 
11695 	cfg_val = nla_get_u8(attr);
11696 	hdd_debug("Configure EPCS capability %s(%d)",
11697 		  cfg_val ? "Enable" : "Disable", cfg_val);
11698 	if (cfg_val < WLAN_EPCS_CAP_DISABLED ||
11699 	    cfg_val > WLAN_EPCS_CAP_ENABLE) {
11700 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11701 		return -EINVAL;
11702 	}
11703 
11704 	ucfg_epcs_set_config(vdev, cfg_val);
11705 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11706 
11707 	return 0;
11708 }
11709 
11710 /**
11711  * hdd_trigger_epcs_function() - Trigger EPCS function to enable or disable
11712  * @link_info: link info pointer
11713  * @attr: pointer to nla attr
11714  *
11715  * Return: 0 on success, negative on failure
11716  */
11717 static int hdd_trigger_epcs_function(struct wlan_hdd_link_info *link_info,
11718 				     const struct nlattr *attr)
11719 {
11720 	uint8_t cfg_val;
11721 	struct wlan_objmgr_vdev *vdev;
11722 	enum wlan_epcs_evt event;
11723 	int status = -EINVAL;
11724 
11725 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
11726 	if (!vdev)
11727 		return status;
11728 
11729 	cfg_val = nla_get_u8(attr);
11730 	hdd_debug("Trigger EPCS %d", cfg_val);
11731 
11732 	switch (cfg_val) {
11733 	/* enable EPCS function to send request frame */
11734 	case WLAN_EPCS_FRAME_REQUEST:
11735 		event = WLAN_EPCS_EV_ACTION_FRAME_TX_REQ;
11736 		break;
11737 	/* disable EPCS function to send teardown frame */
11738 	case WLAN_EPCS_FRAME_TEARDOWN:
11739 		event = WLAN_EPCS_EV_ACTION_FRAME_TX_TEARDOWN;
11740 		break;
11741 	default:
11742 		goto rel_ref;
11743 	}
11744 
11745 	ucfg_epcs_deliver_cmd(vdev, event);
11746 	status = 0;
11747 
11748 rel_ref:
11749 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
11750 	return status;
11751 }
11752 #else
11753 static inline int
11754 hdd_test_config_emlsr_mode(struct hdd_context *hdd_ctx, bool cfg_val)
11755 {
11756 	return 0;
11757 }
11758 
11759 static inline int
11760 hdd_test_config_emlsr_action_mode(struct hdd_adapter *adapter,
11761 				  enum wlan_emlsr_action_mode emlsr_mode)
11762 {
11763 	return 0;
11764 }
11765 #endif
11766 
11767 #ifdef WLAN_FEATURE_11BE
11768 /**
11769  * hdd_set_eht_emlsr_capability() - Set EMLSR capability for EHT STA
11770  * @link_info: Link info pointer in HDD adapter
11771  * @attr: pointer to nla attr
11772  *
11773  * Return: 0 on success, negative on failure
11774  */
11775 static int
11776 hdd_set_eht_emlsr_capability(struct wlan_hdd_link_info *link_info,
11777 			     const struct nlattr *attr)
11778 {
11779 	uint8_t cfg_val;
11780 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11781 
11782 	cfg_val = nla_get_u8(attr);
11783 	hdd_debug("EMLSR capable: %d", cfg_val);
11784 	hdd_test_config_emlsr_mode(hdd_ctx, cfg_val);
11785 
11786 	return 0;
11787 }
11788 
11789 /**
11790  * hdd_set_eht_max_simultaneous_links() - Set EHT maximum number of
11791  * simultaneous links
11792  * @link_info: Link info pointer in HDD adapter
11793  * @attr: pointer to nla attr
11794  *
11795  * Return: 0 on success, negative on failure
11796  */
11797 static int
11798 hdd_set_eht_max_simultaneous_links(struct wlan_hdd_link_info *link_info,
11799 				   const struct nlattr *attr)
11800 {
11801 	uint8_t cfg_val;
11802 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11803 
11804 	cfg_val = nla_get_u8(attr);
11805 	if (cfg_val > MAX_SIMULTANEOUS_STA_ML_LINKS)
11806 		return -EINVAL;
11807 
11808 	sme_set_mlo_max_simultaneous_links(hdd_ctx->mac_handle,
11809 					   link_info->vdev_id, cfg_val);
11810 
11811 	return 0;
11812 }
11813 
11814 /**
11815  * hdd_set_eht_max_num_links() - Set EHT maximum number of links
11816  * @link_info: Link info pointer in HDD adapter
11817  * @attr: pointer to nla attr
11818  *
11819  * Return: 0 on success, negative on failure
11820  */
11821 static int hdd_set_eht_max_num_links(struct wlan_hdd_link_info *link_info,
11822 				     const struct nlattr *attr)
11823 {
11824 	uint8_t cfg_val;
11825 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
11826 
11827 	cfg_val = nla_get_u8(attr);
11828 	if (cfg_val > MAX_NUM_STA_ML_LINKS)
11829 		return -EINVAL;
11830 
11831 	sme_set_mlo_max_links(hdd_ctx->mac_handle,
11832 			      link_info->vdev_id, cfg_val);
11833 
11834 	return 0;
11835 }
11836 
11837 /**
11838  * hdd_get_cfg_eht_mode() - Convert qca wlan EHT mode enum to cfg wlan EHT mode
11839  * @qca_wlan_eht_mode: qca wlan eht mode
11840  *
11841  * Return: EHT mode on success, 0 on failure
11842  */
11843 static enum wlan_eht_mode
11844 hdd_get_cfg_eht_mode(enum qca_wlan_eht_mlo_mode qca_wlan_eht_mode)
11845 {
11846 	switch (qca_wlan_eht_mode) {
11847 	case QCA_WLAN_EHT_MLSR:
11848 		return WLAN_EHT_MODE_MLSR;
11849 	case QCA_WLAN_EHT_EMLSR:
11850 		return WLAN_EHT_MODE_EMLSR;
11851 	case QCA_WLAN_EHT_NON_STR_MLMR:
11852 	case QCA_WLAN_EHT_STR_MLMR:
11853 		return WLAN_EHT_MODE_MLMR;
11854 	default:
11855 		hdd_debug("Invalid EHT mode");
11856 		return WLAN_EHT_MODE_DISABLED;
11857 	}
11858 }
11859 
11860 /**
11861  * hdd_set_eht_mlo_mode() - Set EHT MLO mode of operation
11862  * @link_info: Link info pointer in HDD adapter
11863  * @attr: pointer to nla attr
11864  *
11865  * Return: 0 on success, negative on failure
11866  */
11867 static int hdd_set_eht_mlo_mode(struct wlan_hdd_link_info *link_info,
11868 				const struct nlattr *attr)
11869 {
11870 	uint8_t cfg_val;
11871 	struct hdd_adapter *adapter = link_info->adapter;
11872 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11873 	enum wlan_eht_mode eht_mode;
11874 
11875 	cfg_val = nla_get_u8(attr);
11876 	hdd_debug("Configure EHT mode of operation: %d", cfg_val);
11877 
11878 	eht_mode = hdd_get_cfg_eht_mode(cfg_val);
11879 
11880 	if (eht_mode == WLAN_EHT_MODE_EMLSR &&
11881 	    adapter->device_mode == QDF_STA_MODE) {
11882 		hdd_test_config_emlsr_mode(hdd_ctx, true);
11883 		ucfg_mlme_set_bss_color_collision_det_sta(hdd_ctx->psoc, false);
11884 	}
11885 
11886 	ucfg_mlme_set_eht_mode(hdd_ctx->psoc, eht_mode);
11887 
11888 	return 0;
11889 }
11890 #else
11891 static inline int
11892 hdd_set_eht_emlsr_capability(struct wlan_hdd_link_info *link_info,
11893 			     const struct nlattr *attr)
11894 {
11895 	return 0;
11896 }
11897 
11898 static inline int
11899 hdd_set_eht_max_simultaneous_links(struct wlan_hdd_link_info *link_info,
11900 				   const struct nlattr *attr)
11901 {
11902 	return 0;
11903 }
11904 
11905 static inline int
11906 hdd_set_eht_max_num_links(struct wlan_hdd_link_info  *link_info,
11907 			  const struct nlattr *attr)
11908 {
11909 	return 0;
11910 }
11911 
11912 static inline int
11913 hdd_set_eht_mlo_mode(struct wlan_hdd_link_info *link_info,
11914 		     const struct nlattr *attr)
11915 {
11916 	return 0;
11917 }
11918 #endif
11919 
11920 #ifdef WLAN_FEATURE_11BE_MLO
11921 static int hdd_set_link_force_active(struct wlan_hdd_link_info *link_info,
11922 				     const struct nlattr *attr)
11923 {
11924 	struct hdd_context *hdd_ctx = NULL;
11925 	struct nlattr *curr_attr;
11926 	struct qdf_mac_addr active_link_addr[2];
11927 	struct qdf_mac_addr *mac_addr_ptr;
11928 	uint32_t num_links = 0;
11929 	int32_t len;
11930 	struct hdd_adapter *adapter = link_info->adapter;
11931 
11932 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11933 	if (!hdd_ctx)
11934 		return -EINVAL;
11935 
11936 	if (attr && adapter->device_mode == QDF_STA_MODE) {
11937 		nla_for_each_nested(curr_attr, &attr[0], len) {
11938 			mac_addr_ptr = &active_link_addr[num_links];
11939 			qdf_mem_copy(mac_addr_ptr, nla_data(curr_attr),
11940 				     ETH_ALEN);
11941 			hdd_debug(QDF_MAC_ADDR_FMT " is link[%d] mac address",
11942 				  QDF_MAC_ADDR_REF(mac_addr_ptr->bytes),
11943 				  num_links);
11944 			num_links++;
11945 		}
11946 		sme_activate_mlo_links(hdd_ctx->mac_handle,
11947 				       link_info->vdev_id, num_links,
11948 				       active_link_addr);
11949 	}
11950 	hdd_debug("number of links to force active: %d", num_links);
11951 
11952 	return 0;
11953 }
11954 
11955 /**
11956  * hdd_get_cfg_emlsr_mode() - Convert qca wlan EMLSR mode enum to cfg wlan
11957  * EMLSR action mode
11958  * @qca_wlan_emlsr_mode: qca wlan EMLSR mode
11959  *
11960  * Return: EMLSR mode on success, 0 on failure
11961  */
11962 static enum wlan_emlsr_action_mode
11963 hdd_get_cfg_emlsr_mode(enum qca_wlan_eht_mlo_mode qca_wlan_emlsr_mode)
11964 {
11965 	switch (qca_wlan_emlsr_mode) {
11966 	case QCA_WLAN_EMLSR_MODE_ENTER:
11967 		return WLAN_EMLSR_MODE_ENTER;
11968 	case QCA_WLAN_EMLSR_MODE_EXIT:
11969 		return WLAN_EMLSR_MODE_EXIT;
11970 	default:
11971 		hdd_debug("Invalid EMLSR action mode");
11972 		return WLAN_EMLSR_MODE_DISABLED;
11973 	}
11974 }
11975 
11976 /**
11977  * hdd_get_cfg_t2lm_neg_support_type() - Convert qca wlan TID-to-link mapping
11978  * enum to cfg wlan
11979  *
11980  * @qca_wlan_t2lm_support: qca wlan TID-to-link mapping
11981  *
11982  * Return: TID-to-link mapping support on success, 0 on failure
11983  */
11984 static enum wlan_t2lm_negotiation_support
11985 hdd_get_cfg_t2lm_neg_support_type(enum qca_wlan_ttlm_negotiation_support
11986 				  qca_wlan_t2lm_support)
11987 {
11988 	switch (qca_wlan_t2lm_support) {
11989 	case QCA_WLAN_TTLM_DISABLE:
11990 		return WLAN_T2LM_DISABLE;
11991 	case QCA_WLAN_TTLM_SAME_LINK_SET:
11992 		return WLAN_T2LM_SAME_LINK_SET;
11993 	case QCA_WLAN_TTLM_SAME_DIFF_LINK_SET:
11994 		return WLAN_T2LM_SAME_DIFF_LINK_SET;
11995 	default:
11996 		hdd_debug("Invalid T2LM negotiation support");
11997 		return WLAN_T2LM_DISABLE;
11998 	}
11999 }
12000 
12001 static int hdd_set_emlsr_mode(struct wlan_hdd_link_info *link_info,
12002 			      const struct nlattr *attr)
12003 {
12004 	uint8_t cfg_val;
12005 	enum wlan_emlsr_action_mode emlsr_action_mode;
12006 
12007 	if (!attr)
12008 		return -EINVAL;
12009 
12010 	cfg_val = nla_get_u8(attr);
12011 
12012 	emlsr_action_mode = hdd_get_cfg_emlsr_mode(cfg_val);
12013 
12014 	hdd_debug("EMLSR mode: %s", emlsr_action_mode == WLAN_EMLSR_MODE_ENTER ?
12015 		  "Enter" : "Exit");
12016 
12017 	hdd_test_config_emlsr_action_mode(link_info->adapter,
12018 					  emlsr_action_mode);
12019 
12020 	return 0;
12021 }
12022 
12023 static int hdd_set_t2lm_negotiation_support(struct wlan_hdd_link_info *link_info,
12024 					    const struct nlattr *attr)
12025 {
12026 	struct hdd_context *hdd_ctx = NULL;
12027 	uint8_t cfg_val;
12028 	enum wlan_t2lm_negotiation_support t2lm_support;
12029 
12030 	if (!attr)
12031 		return -EINVAL;
12032 
12033 	cfg_val = nla_get_u8(attr);
12034 
12035 	t2lm_support = hdd_get_cfg_t2lm_neg_support_type(cfg_val);
12036 	hdd_debug("T2LM negotiation support: %d", t2lm_support);
12037 
12038 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12039 
12040 	wlan_mlme_set_t2lm_negotiation_supported(hdd_ctx->psoc,
12041 						 t2lm_support);
12042 
12043 	return 0;
12044 }
12045 #else
12046 static inline int
12047 hdd_set_link_force_active(struct wlan_hdd_link_info *link_info,
12048 			  const struct nlattr *attr)
12049 {
12050 	return 0;
12051 }
12052 
12053 static inline
12054 int hdd_set_emlsr_mode(struct wlan_hdd_link_info *link_info,
12055 		       const struct nlattr *attr)
12056 {
12057 	return 0;
12058 }
12059 
12060 static inline
12061 int hdd_set_t2lm_negotiation_support(struct wlan_hdd_link_info *link_info,
12062 				     const struct nlattr *attr)
12063 {
12064 	return 0;
12065 }
12066 
12067 static inline int
12068 hdd_set_epcs_capability(struct wlan_hdd_link_info *link_info,
12069 			const struct nlattr *attr)
12070 {
12071 	return 0;
12072 }
12073 
12074 static inline int
12075 hdd_trigger_epcs_function(struct wlan_hdd_link_info *link_info,
12076 			  const struct nlattr *attr)
12077 {
12078 	return 0;
12079 }
12080 #endif
12081 
12082 /**
12083  * hdd_set_master_channel_list() - set master channel list from set wifi
12084  * attribute
12085  * @link_info: hdd link info
12086  * @attr: Pointer to struct nlattr
12087  *
12088  * Return: 0 on success, else error number
12089  */
12090 static int
12091 hdd_set_master_channel_list(struct wlan_hdd_link_info *link_info,
12092 			    const struct nlattr *attr)
12093 {
12094 	struct sap_config *sap_config;
12095 	qdf_freq_t freq;
12096 	uint16_t count = 0;
12097 	qdf_freq_t *freq_list;
12098 	struct nlattr *nested_attr;
12099 	int tmp, ret = 0;
12100 
12101 	if (link_info->adapter->device_mode != QDF_SAP_MODE) {
12102 		hdd_debug("command not received for sap");
12103 		return -EINVAL;
12104 	}
12105 	freq_list = qdf_mem_malloc(NUM_CHANNELS * sizeof(qdf_freq_t));
12106 	if (!freq_list)
12107 		return -ENOMEM;
12108 
12109 	sap_config = &link_info->adapter->deflink->session.ap.sap_config;
12110 
12111 	nla_for_each_nested(nested_attr, attr, tmp) {
12112 		freq = nla_get_u32(nested_attr);
12113 		if (!freq) {
12114 			hdd_err("invalid freq");
12115 			ret = -EINVAL;
12116 			goto out;
12117 		}
12118 		freq_list[count] = freq;
12119 		count++;
12120 		if (count >= NUM_CHANNELS)
12121 			break;
12122 	}
12123 	if (!count) {
12124 		hdd_err("no valid freq found");
12125 		ret = -EINVAL;
12126 		goto out;
12127 	}
12128 	ret = wlansap_update_sap_chan_list(sap_config, freq_list, count);
12129 	if (ret)
12130 		hdd_err("sap chan list update failure");
12131 out:
12132 	qdf_mem_free(freq_list);
12133 
12134 	return ret;
12135 }
12136 
12137 /**
12138  * typedef independent_setter_fn - independent attribute handler
12139  * @link_info: Link info pointer in HDD adapter
12140  * @attr: The nl80211 attribute being applied
12141  *
12142  * Defines the signature of functions in the independent attribute vtable
12143  *
12144  * Return: 0 if the attribute was handled successfully, otherwise an errno
12145  */
12146 typedef int (*independent_setter_fn)(struct wlan_hdd_link_info *link_info,
12147 				     const struct nlattr *attr);
12148 
12149 /**
12150  * struct independent_setters
12151  * @id: vendor attribute which this entry handles
12152  * @cb: callback function to invoke to process the attribute when present
12153  */
12154 struct independent_setters {
12155 	uint32_t id;
12156 	independent_setter_fn cb;
12157 };
12158 
12159 /* vtable for independent setters */
12160 static const struct independent_setters independent_setters[] = {
12161 	{QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
12162 	 hdd_config_scan_default_ies},
12163 	{QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT,
12164 	 hdd_config_fine_time_measurement},
12165 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM,
12166 	 hdd_config_dynamic_dtim},
12167 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
12168 	 hdd_config_listen_interval},
12169 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LRO,
12170 	 hdd_config_lro},
12171 	{QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE,
12172 	 hdd_config_scan_enable},
12173 	{QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR,
12174 	 hdd_config_stats_avg_factor},
12175 	{QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME,
12176 	 hdd_config_guard_time},
12177 	{QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY,
12178 	 hdd_config_non_agg_retry},
12179 	{QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY,
12180 	 hdd_config_agg_retry},
12181 	{QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY,
12182 	 hdd_config_mgmt_retry},
12183 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY,
12184 	 hdd_config_ctrl_retry},
12185 	{QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY,
12186 	 hdd_config_propagation_delay},
12187 	{QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY,
12188 	 hdd_config_propagation_abs_delay},
12189 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT,
12190 	 hdd_config_tx_fail_count},
12191 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND,
12192 	 hdd_config_channel_avoidance_ind},
12193 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA,
12194 	 hdd_config_ant_div_ena},
12195 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF,
12196 	 hdd_config_ant_div_snr_diff},
12197 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME,
12198 	 hdd_config_ant_div_probe_dwell_time},
12199 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN,
12200 	 hdd_config_ant_div_chain},
12201 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST,
12202 	 hdd_config_ant_div_selftest},
12203 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL,
12204 	 hdd_config_ant_div_selftest_intvl},
12205 	{QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED,
12206 	 hdd_config_ignore_assoc_disallowed},
12207 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL,
12208 	 hdd_config_restrict_offchannel},
12209 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT,
12210 	 hdd_config_total_beacon_miss_count},
12211 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL,
12212 	 hdd_config_latency_level},
12213 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS,
12214 	 hdd_config_disable_fils},
12215 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE,
12216 	 hdd_config_rsn_ie},
12217 	{QCA_WLAN_VENDOR_ATTR_CONFIG_GTX,
12218 	 hdd_config_gtx},
12219 	{QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES,
12220 	 hdd_config_disconnect_ies},
12221 #ifdef WLAN_FEATURE_ELNA
12222 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
12223 	 hdd_set_elna_bypass},
12224 #endif
12225 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
12226 	 hdd_set_roam_reason_vsie_status},
12227 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC,
12228 	 hdd_config_ldpc},
12229 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC,
12230 	 hdd_config_tx_stbc},
12231 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
12232 	 hdd_config_rx_stbc},
12233 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
12234 	 hdd_set_dynamic_bw},
12235 	{QCA_WLAN_VENDOR_ATTR_CONFIG_NSS,
12236 	 hdd_set_nss},
12237 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE,
12238 	 hdd_config_udp_qos_upgrade_threshold},
12239 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY,
12240 	 hdd_set_primary_interface},
12241 	{QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS,
12242 	 hdd_set_ft_over_ds},
12243 #ifdef FEATURE_WLAN_DYNAMIC_ARP_NS_OFFLOAD
12244 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD,
12245 	 hdd_set_arp_ns_offload},
12246 #endif
12247 #ifdef WLAN_FEATURE_DBAM_CONFIG
12248 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DBAM,
12249 	 hdd_set_dbam_config},
12250 #endif
12251 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE_FOR_BE_BK,
12252 	 hdd_config_udp_qos_upgrade_be_bk},
12253 	{QCA_WLAN_VENDOR_ATTR_CONFIG_BEAMFORMER_PERIODIC_SOUNDING,
12254 	 hdd_set_beamformer_periodic_sounding},
12255 
12256 	{QCA_WLAN_VENDOR_ATTR_CONFIG_WFC_STATE,
12257 	 hdd_set_wfc_state},
12258 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_EML_CAPABILITY,
12259 	 hdd_set_eht_emlsr_capability},
12260 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_SIMULTANEOUS_LINKS,
12261 	 hdd_set_eht_max_simultaneous_links},
12262 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_CAPABILITY,
12263 	 hdd_set_epcs_capability},
12264 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EPCS_FUNCTION,
12265 	 hdd_trigger_epcs_function},
12266 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MAX_NUM_LINKS,
12267 	 hdd_set_eht_max_num_links},
12268 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_MODE,
12269 	 hdd_set_eht_mlo_mode},
12270 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EHT_MLO_ACTIVE_LINKS,
12271 	 hdd_set_link_force_active},
12272 	{QCA_WLAN_VENDOR_ATTR_CONFIG_EMLSR_MODE_SWITCH,
12273 	 hdd_set_emlsr_mode},
12274 	{QCA_WLAN_VENDOR_ATTR_CONFIG_UL_MU_CONFIG,
12275 	 hdd_set_ul_mu_config},
12276 	{QCA_WLAN_VENDOR_ATTR_CONFIG_AP_ALLOWED_FREQ_LIST,
12277 	 hdd_set_master_channel_list},
12278 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TTLM_NEGOTIATION_SUPPORT,
12279 	 hdd_set_t2lm_negotiation_support},
12280 	{QCA_WLAN_VENDOR_ATTR_CONFIG_COEX_TRAFFIC_SHAPING_MODE,
12281 	 hdd_set_coex_traffic_shaping_mode},
12282 };
12283 
12284 #ifdef WLAN_FEATURE_ELNA
12285 /**
12286  * hdd_get_elna_bypass() - Get eLNA bypass
12287  * @link_info: Link info pointer in HDD adapter
12288  * @skb: sk buffer to hold nl80211 attributes
12289  * @attr: Pointer to struct nlattr
12290  *
12291  * Return: 0 on success; error number otherwise
12292  */
12293 static int hdd_get_elna_bypass(struct wlan_hdd_link_info *link_info,
12294 			       struct sk_buff *skb,
12295 			       const struct nlattr *attr)
12296 {
12297 	int ret;
12298 	struct wlan_objmgr_vdev *vdev;
12299 
12300 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_FWOL_NB_ID);
12301 	if (!vdev)
12302 		return -EINVAL;
12303 
12304 	ret = os_if_fwol_get_elna_bypass(vdev, skb, attr);
12305 
12306 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_FWOL_NB_ID);
12307 
12308 	return ret;
12309 }
12310 #endif
12311 
12312 /**
12313  * hdd_get_roam_reason_vsie_status() - Get roam_reason_vsie
12314  * @link_info: Link info pointer in HDD adapter
12315  * @skb: sk buffer to hold nl80211 attributes
12316  * @attr: Pointer to struct nlattr
12317  *
12318  * Return: 0 on success; error number otherwise
12319  */
12320 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
12321 static int hdd_get_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
12322 					   struct sk_buff *skb,
12323 					   const struct nlattr *attr)
12324 {
12325 	uint8_t roam_reason_vsie_enabled;
12326 	struct hdd_context *hdd_ctx = NULL;
12327 	QDF_STATUS status;
12328 
12329 	hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12330 
12331 	status = ucfg_mlme_get_roam_reason_vsie_status
12332 			       (hdd_ctx->psoc,
12333 				&roam_reason_vsie_enabled);
12334 	if (QDF_IS_STATUS_ERROR(status)) {
12335 		hdd_err("get roam reason vsie failed");
12336 		return -EINVAL;
12337 	}
12338 	hdd_debug("is roam_reason_vsie_enabled %d", roam_reason_vsie_enabled);
12339 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
12340 		       roam_reason_vsie_enabled)) {
12341 		hdd_err("nla_put failure");
12342 		return -EINVAL;
12343 	}
12344 
12345 	return 0;
12346 }
12347 #else
12348 static inline int
12349 hdd_get_roam_reason_vsie_status(struct wlan_hdd_link_info *link_info,
12350 				struct sk_buff *skb, const struct nlattr *attr)
12351 {
12352 	return -EINVAL;
12353 }
12354 #endif
12355 
12356 static int hdd_vendor_attr_ldpc_get(struct wlan_hdd_link_info *link_info,
12357 				    struct sk_buff *skb,
12358 				    const struct nlattr *attr)
12359 {
12360 	int ldpc, ret;
12361 
12362 	ret = hdd_get_ldpc(link_info->adapter, &ldpc);
12363 	if (ret) {
12364 		hdd_err("get ldpc failed");
12365 		return -EINVAL;
12366 	}
12367 
12368 	hdd_debug("ldpc %u", ldpc);
12369 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC,
12370 		       (uint8_t)ldpc)) {
12371 		hdd_err("nla_put failure");
12372 		return -EINVAL;
12373 	}
12374 
12375 	return 0;
12376 }
12377 
12378 static int hdd_vendor_attr_tx_stbc_get(struct wlan_hdd_link_info *link_info,
12379 				       struct sk_buff *skb,
12380 				       const struct nlattr *attr)
12381 {
12382 	int tx_stbc;
12383 	int ret;
12384 
12385 	ret = hdd_get_tx_stbc(link_info->adapter, &tx_stbc);
12386 	if (ret) {
12387 		hdd_err("get tx_stbc failed");
12388 		return -EINVAL;
12389 	}
12390 
12391 	hdd_debug("tx_stbc %u", tx_stbc);
12392 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC,
12393 		       (uint8_t)tx_stbc)) {
12394 		hdd_err("nla_put failure");
12395 		return -EINVAL;
12396 	}
12397 
12398 	return 0;
12399 }
12400 
12401 static int hdd_vendor_attr_rx_stbc_get(struct wlan_hdd_link_info *link_info,
12402 				       struct sk_buff *skb,
12403 				       const struct nlattr *attr)
12404 {
12405 	int rx_stbc;
12406 	int ret;
12407 
12408 	ret = hdd_get_rx_stbc(link_info->adapter, &rx_stbc);
12409 	if (ret) {
12410 		hdd_err("get rx_stbc failed");
12411 		return -EINVAL;
12412 	}
12413 
12414 	hdd_debug("rx_stbc %u", rx_stbc);
12415 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
12416 		       (uint8_t)rx_stbc)) {
12417 		hdd_err("nla_put failure");
12418 		return -EINVAL;
12419 	}
12420 
12421 	return 0;
12422 }
12423 
12424 /**
12425  * hdd_get_tx_ampdu() - Get TX AMPDU
12426  * @link_info: Link info in HDD adapter
12427  * @skb: sk buffer to hold nl80211 attributes
12428  * @attr: Pointer to struct nlattr
12429  *
12430  * Return: 0 on success; error number otherwise
12431  */
12432 static int hdd_get_tx_ampdu(struct wlan_hdd_link_info *link_info,
12433 			    struct sk_buff *skb, const struct nlattr *attr)
12434 {
12435 	int value;
12436 
12437 	value = wma_cli_get_command(link_info->vdev_id,
12438 				    GEN_VDEV_PARAM_TX_AMPDU, GEN_CMD);
12439 	if (value < 0) {
12440 		hdd_err("Failed to get tx_ampdu");
12441 		return -EINVAL;
12442 	}
12443 
12444 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION,
12445 		       (uint8_t)value)) {
12446 		hdd_err("nla_put failure");
12447 		return -EINVAL;
12448 	}
12449 
12450 	return 0;
12451 }
12452 
12453 /**
12454  * hdd_get_rx_ampdu() - Get RX AMPDU
12455  * @link_info: Link info in HDD adapter
12456  * @skb: sk buffer to hold nl80211 attributes
12457  * @attr: Pointer to struct nlattr
12458  *
12459  * Return: 0 on success; error number otherwise
12460  */
12461 static int hdd_get_rx_ampdu(struct wlan_hdd_link_info *link_info,
12462 			    struct sk_buff *skb, const struct nlattr *attr)
12463 {
12464 	int value;
12465 
12466 	value = wma_cli_get_command(link_info->vdev_id,
12467 				    GEN_VDEV_PARAM_RX_AMPDU, GEN_CMD);
12468 	if (value < 0) {
12469 		hdd_err("Failed to get rx_ampdu");
12470 		return -EINVAL;
12471 	}
12472 
12473 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION,
12474 		       (uint8_t)value)) {
12475 		hdd_err("nla_put failure");
12476 		return -EINVAL;
12477 	}
12478 
12479 	return 0;
12480 }
12481 
12482 /**
12483  * hdd_get_tx_amsdu() - Get TX AMSDU
12484  * @link_info: Link info pointer in HDD adapter
12485  * @skb: sk buffer to hold nl80211 attributes
12486  * @attr: Pointer to struct nlattr
12487  *
12488  * Return: 0 on success; error number otherwise
12489  */
12490 static int hdd_get_tx_amsdu(struct wlan_hdd_link_info *link_info,
12491 			    struct sk_buff *skb, const struct nlattr *attr)
12492 {
12493 	int value;
12494 
12495 	value = wma_cli_get_command(link_info->vdev_id,
12496 				    GEN_VDEV_PARAM_TX_AMSDU, GEN_CMD);
12497 	if (value < 0) {
12498 		hdd_err("Failed to get tx_amsdu");
12499 		return -EINVAL;
12500 	}
12501 
12502 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION,
12503 		       (uint8_t)value)) {
12504 		hdd_err("nla_put failure");
12505 		return -EINVAL;
12506 	}
12507 
12508 	return 0;
12509 }
12510 
12511 /**
12512  * hdd_get_rx_amsdu() - Get RX AMSDU
12513  * @link_info: Link info pointer in HDD adapter
12514  * @skb: sk buffer to hold nl80211 attributes
12515  * @attr: Pointer to struct nlattr
12516  *
12517  * Return: 0 on success; error number otherwise
12518  */
12519 static int hdd_get_rx_amsdu(struct wlan_hdd_link_info *link_info,
12520 			    struct sk_buff *skb, const struct nlattr *attr)
12521 {
12522 	int value;
12523 
12524 	value = wma_cli_get_command(link_info->vdev_id,
12525 				    GEN_VDEV_PARAM_RX_AMSDU, GEN_CMD);
12526 	if (value < 0) {
12527 		hdd_err("Failed to get rx_amsdu");
12528 		return -EINVAL;
12529 	}
12530 
12531 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION,
12532 		       (uint8_t)value)) {
12533 		hdd_err("nla_put failure");
12534 		return -EINVAL;
12535 	}
12536 
12537 	return 0;
12538 }
12539 
12540 /**
12541  * hdd_get_channel_width() - Get channel width
12542  * @link_info: Link info pointer in HDD adapter
12543  * @skb: sk buffer to hold nl80211 attributes
12544  * @attr: Pointer to struct nlattr
12545  *
12546  * Return: 0 on success; error number otherwise
12547  */
12548 static int hdd_get_channel_width(struct wlan_hdd_link_info *link_info,
12549 				 struct sk_buff *skb, const struct nlattr *attr)
12550 {
12551 	uint8_t nl80211_chwidth;
12552 	struct wlan_channel *bss_chan;
12553 	struct wlan_objmgr_vdev *vdev;
12554 
12555 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
12556 	if (!vdev)
12557 		return -EINVAL;
12558 
12559 	bss_chan = wlan_vdev_mlme_get_bss_chan(vdev);
12560 	if (!bss_chan) {
12561 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12562 		hdd_err("get bss_chan failed");
12563 		return QDF_STATUS_E_FAILURE;
12564 	}
12565 
12566 	nl80211_chwidth = hdd_phy_chwidth_to_nl80211_chwidth(bss_chan->ch_width);
12567 	if (nla_put_u8(skb, CONFIG_CHANNEL_WIDTH, nl80211_chwidth)) {
12568 		hdd_err("nla_put chn width failure");
12569 		return -EINVAL;
12570 	}
12571 
12572 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12573 	return 0;
12574 }
12575 
12576 /**
12577  * hdd_get_mlo_max_band_info() - Get channel width
12578  * @link_info: Link info pointer in HDD adapter
12579  * @skb: sk buffer to hold nl80211 attributes
12580  * @attr: Pointer to struct nlattr
12581  *
12582  * Return: 0 on success; error number otherwise
12583  */
12584 static int hdd_get_mlo_max_band_info(struct wlan_hdd_link_info *link_info,
12585 				     struct sk_buff *skb,
12586 				     const struct nlattr *attr)
12587 {
12588 	enum eSirMacHTChannelWidth chwidth;
12589 	struct nlattr *mlo_bd = NULL;
12590 	struct nlattr *mlo_bd_info = NULL;
12591 	uint32_t i = 0;
12592 	uint32_t link_id = 0;
12593 	struct wlan_objmgr_vdev *vdev, *link_vdev;
12594 	struct wlan_channel *bss_chan;
12595 	uint8_t nl80211_chwidth;
12596 	int8_t ret = 0;
12597 
12598 	chwidth = wma_cli_get_command(link_info->vdev_id,
12599 				      wmi_vdev_param_chwidth, VDEV_CMD);
12600 	if (chwidth < 0) {
12601 		hdd_err("Failed to get chwidth %u", chwidth);
12602 		return -EINVAL;
12603 	}
12604 
12605 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
12606 	if (!vdev)
12607 		return -EINVAL;
12608 
12609 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
12610 		mlo_bd_info = nla_nest_start(skb, CONFIG_MLO_LINKS);
12611 		for (link_id = 0; link_id < WLAN_MAX_LINK_ID; link_id++) {
12612 			link_vdev = mlo_get_vdev_by_link_id(vdev, link_id,
12613 							    WLAN_OSIF_ID);
12614 			if (!link_vdev)
12615 				continue;
12616 
12617 			mlo_bd = nla_nest_start(skb, i);
12618 			if (!mlo_bd) {
12619 				hdd_err("nla_nest_start fail");
12620 				ret = -EINVAL;
12621 				goto end;
12622 			}
12623 			bss_chan = wlan_vdev_mlme_get_bss_chan(link_vdev);
12624 			if (!bss_chan) {
12625 				hdd_err("fail to get bss_chan info");
12626 				ret = -EINVAL;
12627 				goto end;
12628 			}
12629 			if (nla_put_u8(skb, CONFIG_MLO_LINK_ID, link_id)) {
12630 				hdd_err("nla_put failure");
12631 				ret = -EINVAL;
12632 				goto end;
12633 			}
12634 
12635 			nl80211_chwidth = hdd_phy_chwidth_to_nl80211_chwidth(bss_chan->ch_width);
12636 			if (nla_put_u8(skb, CONFIG_CHANNEL_WIDTH,
12637 				       nl80211_chwidth)) {
12638 				hdd_err("nla_put failure");
12639 				ret = -EINVAL;
12640 				goto end;
12641 			}
12642 			nla_nest_end(skb, mlo_bd);
12643 			i++;
12644 			hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
12645 		}
12646 		nla_nest_end(skb, mlo_bd_info);
12647 	}
12648 
12649 end:
12650 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12651 
12652 	if (ret)
12653 		hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
12654 
12655 	return ret;
12656 }
12657 
12658 /**
12659  * hdd_get_dynamic_bw() - Get dynamic bandwidth disabled / enabled
12660  * @link_info: Link info pointer in HDD adapter
12661  * @skb: sk buffer to hold nl80211 attributes
12662  * @attr: Pointer to struct nlattr
12663  *
12664  * Return: 0 on success; error number otherwise
12665  */
12666 static int hdd_get_dynamic_bw(struct wlan_hdd_link_info *link_info,
12667 			      struct sk_buff *skb, const struct nlattr *attr)
12668 {
12669 	int enable;
12670 
12671 	enable = wma_cli_get_command(link_info->vdev_id,
12672 				     wmi_pdev_param_dynamic_bw, PDEV_CMD);
12673 	if (enable < 0) {
12674 		hdd_err("Failed to get dynamic_bw");
12675 		return -EINVAL;
12676 	}
12677 
12678 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
12679 		       (uint8_t)enable)) {
12680 		hdd_err("nla_put failure");
12681 		return -EINVAL;
12682 	}
12683 
12684 	return 0;
12685 }
12686 
12687 /**
12688  * hdd_get_nss_config() - Get the number of spatial streams supported by
12689  * the adapter
12690  * @link_info: Link info pointer in HDD adapter
12691  * @skb: sk buffer to hold nl80211 attributes
12692  * @attr: Pointer to struct nlattr
12693  *
12694  * Return: 0 on success; error number otherwise
12695  */
12696 static int hdd_get_nss_config(struct wlan_hdd_link_info *link_info,
12697 			      struct sk_buff *skb, const struct nlattr *attr)
12698 {
12699 	uint8_t nss;
12700 	struct hdd_adapter *adapter = link_info->adapter;
12701 
12702 	if (adapter->device_mode == QDF_SAP_MODE) {
12703 		int value;
12704 
12705 		value = wma_cli_get_command(link_info->vdev_id,
12706 					    wmi_vdev_param_nss, VDEV_CMD);
12707 		if (value < 0) {
12708 			hdd_err("Failed to get nss");
12709 			return -EINVAL;
12710 		}
12711 		nss = (uint8_t)value;
12712 	} else {
12713 		QDF_STATUS status;
12714 
12715 		status = hdd_get_nss(adapter, &nss);
12716 		if (!QDF_IS_STATUS_SUCCESS(status)) {
12717 			hdd_err("Failed to get nss");
12718 			return -EINVAL;
12719 		}
12720 	}
12721 
12722 	hdd_debug("nss %d", nss);
12723 
12724 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_NSS, nss)) {
12725 		hdd_err("nla_put failure");
12726 		return -EINVAL;
12727 	}
12728 
12729 	return 0;
12730 }
12731 
12732 /**
12733  * hdd_get_num_tx_chains_config() - Get the number of tx chains supported by
12734  * the adapter
12735  * @link_info: Link info pointer in HDD adapter
12736  * @skb: sk buffer to hold nl80211 attributes
12737  * @attr: Pointer to struct nlattr
12738  *
12739  * Return: 0 on success; error number otherwise
12740  */
12741 static int hdd_get_num_tx_chains_config(struct wlan_hdd_link_info *link_info,
12742 					struct sk_buff *skb,
12743 					const struct nlattr *attr)
12744 {
12745 	uint8_t tx_chains;
12746 	QDF_STATUS status;
12747 
12748 	if (!hdd_is_vdev_in_conn_state(link_info)) {
12749 		hdd_err("Not in connected state");
12750 		return -EINVAL;
12751 	}
12752 
12753 	status = hdd_get_num_tx_chains(link_info, &tx_chains);
12754 	if (!QDF_IS_STATUS_SUCCESS(status)) {
12755 		hdd_err("Failed to get num tx chains");
12756 		return -EINVAL;
12757 	}
12758 
12759 	hdd_debug("num_tx_chains %d", tx_chains);
12760 	if (nla_put_u8(skb,
12761 		       QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS, tx_chains)) {
12762 		hdd_err("nla_put failure");
12763 		return -EINVAL;
12764 	}
12765 
12766 	return 0;
12767 }
12768 
12769 /**
12770  * hdd_get_tx_nss_config() - Get the number of tx spatial streams supported by
12771  * the adapter
12772  * @link_info: Link info pointer in HDD adapter
12773  * @skb: sk buffer to hold nl80211 attributes
12774  * @attr: Pointer to struct nlattr
12775  *
12776  * Return: 0 on success; error number otherwise
12777  */
12778 static int hdd_get_tx_nss_config(struct wlan_hdd_link_info *link_info,
12779 				 struct sk_buff *skb, const struct nlattr *attr)
12780 {
12781 	uint8_t tx_nss;
12782 	QDF_STATUS status;
12783 
12784 	if (!hdd_is_vdev_in_conn_state(link_info)) {
12785 		hdd_err("Not in connected state");
12786 		return -EINVAL;
12787 	}
12788 
12789 	status = hdd_get_tx_nss(link_info, &tx_nss);
12790 	if (!QDF_IS_STATUS_SUCCESS(status)) {
12791 		hdd_err("Failed to get nss");
12792 		return -EINVAL;
12793 	}
12794 
12795 	hdd_debug("tx_nss %d", tx_nss);
12796 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS, tx_nss)) {
12797 		hdd_err("nla_put failure");
12798 		return -EINVAL;
12799 	}
12800 
12801 	return 0;
12802 }
12803 
12804 /**
12805  * hdd_get_num_rx_chains_config() - Get the number of rx chains supported by
12806  * the adapter
12807  * @link_info: Link info pointer in HDD adapter
12808  * @skb: sk buffer to hold nl80211 attributes
12809  * @attr: Pointer to struct nlattr
12810  *
12811  * Return: 0 on success; error number otherwise
12812  */
12813 static int hdd_get_num_rx_chains_config(struct wlan_hdd_link_info *link_info,
12814 					struct sk_buff *skb,
12815 					const struct nlattr *attr)
12816 {
12817 	uint8_t rx_chains;
12818 	QDF_STATUS status;
12819 
12820 	if (!hdd_is_vdev_in_conn_state(link_info)) {
12821 		hdd_err("Not in connected state");
12822 		return -EINVAL;
12823 	}
12824 
12825 	status = hdd_get_num_rx_chains(link_info, &rx_chains);
12826 	if (!QDF_IS_STATUS_SUCCESS(status)) {
12827 		hdd_err("Failed to get num rx chains");
12828 		return -EINVAL;
12829 	}
12830 
12831 	hdd_debug("num_rx_chains %d", rx_chains);
12832 	if (nla_put_u8(skb,
12833 		       QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS, rx_chains)) {
12834 		hdd_err("nla_put failure");
12835 		return -EINVAL;
12836 	}
12837 
12838 	return 0;
12839 }
12840 
12841 /**
12842  * hdd_get_rx_nss_config() - Get the number of rx spatial streams supported by
12843  * the adapter
12844  * @link_info: Link info pointer in HDD adapter
12845  * @skb: sk buffer to hold nl80211 attributes
12846  * @attr: Pointer to struct nlattr
12847  *
12848  * Return: 0 on success; error number otherwise
12849  */
12850 static int hdd_get_rx_nss_config(struct wlan_hdd_link_info *link_info,
12851 				 struct sk_buff *skb, const struct nlattr *attr)
12852 {
12853 	uint8_t rx_nss;
12854 	QDF_STATUS status;
12855 
12856 	if (!hdd_is_vdev_in_conn_state(link_info)) {
12857 		hdd_err("Not in connected state");
12858 		return -EINVAL;
12859 	}
12860 
12861 	status = hdd_get_rx_nss(link_info, &rx_nss);
12862 	if (!QDF_IS_STATUS_SUCCESS(status)) {
12863 		hdd_err("Failed to get nss");
12864 		return -EINVAL;
12865 	}
12866 
12867 	hdd_debug("rx_nss %d", rx_nss);
12868 	if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS, rx_nss)) {
12869 		hdd_err("nla_put failure");
12870 		return -EINVAL;
12871 	}
12872 
12873 	return 0;
12874 }
12875 
12876 /**
12877  * hdd_get_listen_interval_config() - Get listen interval from driver
12878  * @link_info: Link info pointer in HDD adapter
12879  * @skb: sk buffer to hold nl80211 attributes
12880  * @attr: Pointer to struct nlattr
12881  *
12882  * Return: 0 on success; error number otherwise
12883  */
12884 static int hdd_get_listen_interval_config(struct wlan_hdd_link_info *link_info,
12885 					  struct sk_buff *skb,
12886 					  const struct nlattr *attr)
12887 {
12888 	uint32_t listen_interval = 0;
12889 	QDF_STATUS status;
12890 	struct hdd_adapter *adapter = link_info->adapter;
12891 	struct wlan_objmgr_vdev *vdev;
12892 
12893 	if (adapter->device_mode != QDF_STA_MODE &&
12894 	    adapter->device_mode != QDF_P2P_CLIENT_MODE) {
12895 		hdd_err("Device not in STA / P2P-CLI mode");
12896 		return -EINVAL;
12897 	}
12898 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
12899 	if (!vdev) {
12900 		hdd_err("Failed to get vdev");
12901 		return -EINVAL;
12902 	}
12903 
12904 	status = ucfg_pmo_get_listen_interval(vdev, &listen_interval);
12905 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
12906 	if (status != QDF_STATUS_SUCCESS) {
12907 		hdd_err("vdev/vdev ctx NULL for getting listen interval");
12908 		return -EINVAL;
12909 	}
12910 
12911 	hdd_debug("listen interval %d", listen_interval);
12912 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
12913 			listen_interval)) {
12914 		hdd_err("nla_put failure");
12915 		return -EINVAL;
12916 	}
12917 
12918 	return 0;
12919 }
12920 
12921 /**
12922  * hdd_get_optimized_power_config() - Get the number of spatial streams
12923  * supported by the adapter
12924  * @link_info: Link info pointer in HDD adapter
12925  * @skb: sk buffer to hold nl80211 attributes
12926  * @attr: Pointer to struct nlattr
12927  *
12928  * Return: 0 on success; error number otherwise
12929  */
12930 static int hdd_get_optimized_power_config(struct wlan_hdd_link_info *link_info,
12931 					  struct sk_buff *skb,
12932 					  const struct nlattr *attr)
12933 {
12934 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
12935 	uint8_t optimized_power_cfg;
12936 	int errno;
12937 
12938 	errno = wlan_hdd_validate_context(hdd_ctx);
12939 	if (errno)
12940 		return errno;
12941 
12942 	optimized_power_cfg  = ucfg_pmo_get_power_save_mode(hdd_ctx->psoc);
12943 
12944 	if (nla_put_u8(skb,
12945 		       QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT,
12946 		       optimized_power_cfg)) {
12947 		hdd_err_rl("nla_put failure");
12948 		return -EINVAL;
12949 	}
12950 
12951 	return 0;
12952 }
12953 
12954 /**
12955  * typedef config_getter_fn - get configuration handler
12956  * @link_info: Link info pointer in HDD adapter
12957  * @skb: sk buffer to hold nl80211 attributes
12958  * @attr: The nl80211 attribute being applied
12959  *
12960  * Defines the signature of functions in the attribute vtable
12961  *
12962  * Return: 0 if the attribute was handled successfully, otherwise an errno
12963  */
12964 typedef int (*config_getter_fn)(struct wlan_hdd_link_info *link_info,
12965 				struct sk_buff *skb,
12966 				const struct nlattr *attr);
12967 
12968 /**
12969  * struct config_getters
12970  * @id: vendor attribute which this entry handles
12971  * @max_attr_len: Maximum length of the attribute
12972  * @cb: callback function to invoke to process the attribute when present
12973  */
12974 struct config_getters {
12975 	uint32_t id;
12976 	size_t max_attr_len;
12977 	config_getter_fn cb;
12978 };
12979 
12980 /* vtable for config getters */
12981 static const struct config_getters config_getters[] = {
12982 #ifdef WLAN_FEATURE_ELNA
12983 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
12984 	 sizeof(uint8_t),
12985 	 hdd_get_elna_bypass},
12986 #endif
12987 	{QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON,
12988 	 sizeof(uint8_t),
12989 	 hdd_get_roam_reason_vsie_status},
12990 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION,
12991 	 sizeof(uint8_t),
12992 	 hdd_get_tx_ampdu},
12993 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION,
12994 	 sizeof(uint8_t),
12995 	 hdd_get_rx_ampdu},
12996 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION,
12997 	 sizeof(uint8_t),
12998 	 hdd_get_tx_amsdu},
12999 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION,
13000 	 sizeof(uint8_t),
13001 	 hdd_get_rx_amsdu},
13002 	{QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC,
13003 	 sizeof(uint8_t),
13004 	 hdd_vendor_attr_ldpc_get},
13005 	{QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC,
13006 	 sizeof(uint8_t),
13007 	 hdd_vendor_attr_tx_stbc_get},
13008 	{QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC,
13009 	 sizeof(uint8_t),
13010 	 hdd_vendor_attr_rx_stbc_get},
13011 	{QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH,
13012 	 sizeof(uint8_t),
13013 	 hdd_get_channel_width},
13014 	{QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW,
13015 	 sizeof(uint8_t),
13016 	 hdd_get_dynamic_bw},
13017 	{QCA_WLAN_VENDOR_ATTR_CONFIG_NSS,
13018 	 sizeof(uint8_t),
13019 	 hdd_get_nss_config},
13020 	{QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT,
13021 	 sizeof(uint8_t),
13022 	 hdd_get_optimized_power_config},
13023 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS,
13024 	 sizeof(uint8_t),
13025 	 hdd_get_tx_nss_config},
13026 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS,
13027 	 sizeof(uint8_t),
13028 	 hdd_get_rx_nss_config},
13029 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL,
13030 	 sizeof(uint32_t),
13031 	 hdd_get_listen_interval_config},
13032 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS,
13033 	 sizeof(uint8_t),
13034 	 hdd_get_num_tx_chains_config},
13035 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS,
13036 	 sizeof(uint8_t),
13037 	 hdd_get_num_rx_chains_config},
13038 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS,
13039 	 WLAN_MAX_ML_BSS_LINKS * sizeof(uint8_t) * 2,
13040 	 hdd_get_mlo_max_band_info},
13041 };
13042 
13043 /**
13044  * hdd_get_configuration() - Handle get configuration
13045  * @link_info: Link info pointer in HDD adapter
13046  * @tb: parsed attribute array
13047  *
13048  * This is a table-driven function which dispatches attributes
13049  * in a QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION
13050  * vendor command.
13051  *
13052  * Return: 0 if there were no issues, otherwise errno of the last issue
13053  */
13054 static int hdd_get_configuration(struct wlan_hdd_link_info *link_info,
13055 				 struct nlattr **tb)
13056 {
13057 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
13058 	uint32_t i, id;
13059 	unsigned long nl_buf_len = NLMSG_HDRLEN;
13060 	struct sk_buff *skb;
13061 	struct nlattr *attr;
13062 	config_getter_fn cb;
13063 	int errno = 0;
13064 
13065 	for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
13066 		id = config_getters[i].id;
13067 		attr = tb[id];
13068 		if (!attr)
13069 			continue;
13070 
13071 		nl_buf_len += NLA_HDRLEN +
13072 			      NLA_ALIGN(config_getters[i].max_attr_len);
13073 	}
13074 
13075 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
13076 						       nl_buf_len);
13077 	if (!skb) {
13078 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
13079 		return -ENOMEM;
13080 	}
13081 
13082 	for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
13083 		id = config_getters[i].id;
13084 		attr = tb[id];
13085 		if (!attr)
13086 			continue;
13087 
13088 		hdd_debug("Get wifi configuration %d", id);
13089 
13090 		cb = config_getters[i].cb;
13091 		errno = cb(link_info, skb, attr);
13092 		if (errno)
13093 			break;
13094 	}
13095 
13096 	if (errno) {
13097 		hdd_err("Failed to get wifi configuration, errno = %d", errno);
13098 		wlan_cfg80211_vendor_free_skb(skb);
13099 		return -EINVAL;
13100 	}
13101 
13102 	wlan_cfg80211_vendor_cmd_reply(skb);
13103 
13104 	return errno;
13105 }
13106 
13107 /**
13108  * hdd_set_independent_configuration() - Handle independent attributes
13109  * @link_info: Link info pointer in HDD adapter
13110  * @tb: parsed attribute array
13111  *
13112  * This is a table-driven function which dispatches independent
13113  * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
13114  * vendor command. An attribute is considered independent if it
13115  * doesn't depend upon any other attributes
13116  *
13117  * Return: 0 if there were no issues, otherwise errno of the last issue
13118  */
13119 static int
13120 hdd_set_independent_configuration(struct wlan_hdd_link_info *link_info,
13121 				  struct nlattr **tb)
13122 {
13123 	uint32_t i;
13124 	uint32_t id;
13125 	struct nlattr *attr;
13126 	independent_setter_fn cb;
13127 	int errno = 0;
13128 	int ret;
13129 
13130 	for (i = 0; i < QDF_ARRAY_SIZE(independent_setters); i++) {
13131 		id = independent_setters[i].id;
13132 		attr = tb[id];
13133 		if (!attr)
13134 			continue;
13135 
13136 		hdd_debug("Set wifi configuration %d", id);
13137 
13138 		cb = independent_setters[i].cb;
13139 		ret = cb(link_info, attr);
13140 		if (ret)
13141 			errno = ret;
13142 	}
13143 
13144 	return errno;
13145 }
13146 
13147 /**
13148  * typedef interdependent_setter_fn - interdependent attribute handler
13149  * @link_info: Link info pointer in HDD adapter
13150  * @tb: The parsed nl80211 attributes being applied
13151  *
13152  * Defines the signature of functions in the interdependent attribute vtable
13153  *
13154  * Return: 0 if attributes were handled successfully, otherwise an errno
13155  */
13156 typedef int (*interdependent_setter_fn)(struct wlan_hdd_link_info *link_info,
13157 					struct nlattr **tb);
13158 
13159 /* vtable for interdependent setters */
13160 static const interdependent_setter_fn interdependent_setters[] = {
13161 	hdd_config_access_policy,
13162 	hdd_config_mpdu_aggregation,
13163 	hdd_config_ant_div_period,
13164 	hdd_config_ant_div_snr_weight,
13165 	wlan_hdd_cfg80211_wifi_set_reorder_timeout,
13166 	wlan_hdd_cfg80211_wifi_set_rx_blocksize,
13167 	hdd_config_msdu_aggregation,
13168 	hdd_config_vdev_chains,
13169 	hdd_config_ani,
13170 	hdd_config_tx_rx_nss,
13171 	hdd_process_generic_set_cmd,
13172 	hdd_config_phy_mode,
13173 	hdd_config_power,
13174 	hdd_set_channel_width,
13175 	hdd_config_peer_ampdu,
13176 };
13177 
13178 /**
13179  * hdd_set_interdependent_configuration() - Handle interdependent attributes
13180  * @link_info: Link info pointer in hdd adapter
13181  * @tb: parsed attribute array
13182  *
13183  * This is a table-driven function which handles interdependent
13184  * attributes in a QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION
13185  * vendor command. A set of attributes is considered interdependent if
13186  * they depend upon each other. In the typical case if one of the
13187  * attributes is present in the the attribute array, then all of the
13188  * attributes must be present.
13189  *
13190  * Return: 0 if there were no issues, otherwise errno of the last issue
13191  */
13192 static int
13193 hdd_set_interdependent_configuration(struct wlan_hdd_link_info *link_info,
13194 				     struct nlattr **tb)
13195 {
13196 	uint32_t i;
13197 	interdependent_setter_fn cb;
13198 	int errno = 0;
13199 	int ret;
13200 
13201 	for (i = 0; i < QDF_ARRAY_SIZE(interdependent_setters); i++) {
13202 		cb = interdependent_setters[i];
13203 		ret = cb(link_info, tb);
13204 		if (ret)
13205 			errno = ret;
13206 	}
13207 
13208 	return errno;
13209 }
13210 
13211 /**
13212  * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
13213  * vendor command
13214  *
13215  * @wiphy: wiphy device pointer
13216  * @wdev: wireless device pointer
13217  * @data: Vendor command data buffer
13218  * @data_len: Buffer length
13219  *
13220  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
13221  *
13222  * Return: Error code.
13223  */
13224 static int
13225 __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
13226 					   struct wireless_dev *wdev,
13227 					   const void *data,
13228 					   int data_len)
13229 {
13230 	struct net_device *dev = wdev->netdev;
13231 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13232 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
13233 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
13234 	int errno, ret;
13235 
13236 	hdd_enter_dev(dev);
13237 
13238 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13239 		hdd_err("Command not allowed in FTM mode");
13240 		return -EPERM;
13241 	}
13242 
13243 	errno = wlan_hdd_validate_context(hdd_ctx);
13244 	if (errno)
13245 		return errno;
13246 
13247 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
13248 				    data_len, wlan_hdd_wifi_config_policy)) {
13249 		hdd_err("invalid attr");
13250 		return -EINVAL;
13251 	}
13252 
13253 	ret = hdd_set_independent_configuration(adapter->deflink, tb);
13254 	if (ret)
13255 		errno = ret;
13256 
13257 	ret = hdd_set_interdependent_configuration(adapter->deflink, tb);
13258 	if (ret)
13259 		errno = ret;
13260 
13261 	return errno;
13262 }
13263 
13264 /**
13265  * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
13266  * vendor command
13267  *
13268  * @wiphy: wiphy device pointer
13269  * @wdev: wireless device pointer
13270  * @data: Vendor command data buffer
13271  * @data_len: Buffer length
13272  *
13273  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
13274  *
13275  * Return: EOK or other error codes.
13276  */
13277 static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
13278 						    struct wireless_dev *wdev,
13279 						    const void *data,
13280 						    int data_len)
13281 {
13282 	int errno;
13283 	struct osif_vdev_sync *vdev_sync;
13284 
13285 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13286 	if (errno)
13287 		return errno;
13288 
13289 	errno = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
13290 							   data, data_len);
13291 
13292 	osif_vdev_sync_op_stop(vdev_sync);
13293 
13294 	return errno;
13295 }
13296 
13297 /**
13298  * __wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
13299  * vendor command
13300  * @wiphy: wiphy device pointer
13301  * @wdev: wireless device pointer
13302  * @data: Vendor command data buffer
13303  * @data_len: Buffer length
13304  *
13305  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
13306  *
13307  * Return: Error code.
13308  */
13309 static int
13310 __wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
13311 					   struct wireless_dev *wdev,
13312 					   const void *data,
13313 					   int data_len)
13314 {
13315 	struct net_device *dev = wdev->netdev;
13316 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13317 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
13318 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
13319 	int errno, ret;
13320 
13321 	hdd_enter_dev(dev);
13322 
13323 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13324 		hdd_err("Command not allowed in FTM mode");
13325 		return -EPERM;
13326 	}
13327 
13328 	errno = wlan_hdd_validate_context(hdd_ctx);
13329 	if (errno)
13330 		return errno;
13331 
13332 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
13333 				    data_len, wlan_hdd_wifi_config_policy)) {
13334 		hdd_err("invalid attr");
13335 		return -EINVAL;
13336 	}
13337 
13338 	/* Generic command is used by EasyMesh,
13339 	 * route the command to SON module if it is Generic
13340 	 *
13341 	 * GENERIC_COMMAND to get configs can not be done as part of dispatch
13342 	 * table because, for each command sent as part of GENERIC command,
13343 	 * return value is different and is handled in SON module as well.
13344 	 * Hence having return type with dispatch table is not possible as
13345 	 * we will not be able to generalize the return for each of get sub
13346 	 * command sent as part of GENERIC command.
13347 	 */
13348 	if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND])
13349 		return hdd_son_send_get_wifi_generic_command(wiphy, wdev, tb);
13350 
13351 	ret = hdd_get_configuration(adapter->deflink, tb);
13352 	if (ret)
13353 		errno = ret;
13354 
13355 	return errno;
13356 }
13357 
13358 /**
13359  * wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
13360  * vendor command
13361  *
13362  * @wiphy: wiphy device pointer
13363  * @wdev: wireless device pointer
13364  * @data: Vendor command data buffer
13365  * @data_len: Buffer length
13366  *
13367  * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
13368  *
13369  * Return: EOK or other error codes.
13370  */
13371 static int wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
13372 						    struct wireless_dev *wdev,
13373 						    const void *data,
13374 						    int data_len)
13375 {
13376 	int errno;
13377 	struct osif_vdev_sync *vdev_sync;
13378 
13379 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
13380 	if (errno)
13381 		return errno;
13382 
13383 	errno = __wlan_hdd_cfg80211_wifi_configuration_get(wiphy, wdev,
13384 							   data, data_len);
13385 
13386 	osif_vdev_sync_op_stop(vdev_sync);
13387 
13388 	return errno;
13389 }
13390 
13391 static void hdd_disable_runtime_pm_for_user(struct hdd_context *hdd_ctx)
13392 {
13393 	struct hdd_runtime_pm_context *ctx = &hdd_ctx->runtime_context;
13394 
13395 	if (!ctx)
13396 		return;
13397 
13398 	if (ctx->is_user_wakelock_acquired)
13399 		return;
13400 
13401 	ctx->is_user_wakelock_acquired = true;
13402 	qdf_runtime_pm_prevent_suspend(&ctx->user);
13403 }
13404 
13405 static int hdd_test_config_6ghz_security_test_mode(struct hdd_context *hdd_ctx,
13406 						   struct nlattr *attr)
13407 
13408 {
13409 	uint8_t cfg_val;
13410 	bool rf_test_mode = false;
13411 	QDF_STATUS status;
13412 
13413 	status = ucfg_mlme_is_rf_test_mode_enabled(hdd_ctx->psoc,
13414 						   &rf_test_mode);
13415 	if (!QDF_IS_STATUS_SUCCESS(status)) {
13416 		hdd_err("Get rf test mode failed");
13417 		return -EINVAL;
13418 	}
13419 	if (rf_test_mode) {
13420 		hdd_err("rf test mode is enabled, ignore setting");
13421 		return 0;
13422 	}
13423 
13424 	cfg_val = nla_get_u8(attr);
13425 	hdd_debug("safe mode setting %d", cfg_val);
13426 	wlan_mlme_set_safe_mode_enable(hdd_ctx->psoc, cfg_val);
13427 	if (cfg_val) {
13428 		wlan_cm_set_check_6ghz_security(hdd_ctx->psoc, false);
13429 		wlan_cm_set_6ghz_key_mgmt_mask(hdd_ctx->psoc,
13430 					       DEFAULT_KEYMGMT_6G_MASK);
13431 	} else {
13432 		wlan_cm_set_check_6ghz_security(hdd_ctx->psoc, true);
13433 		wlan_cm_set_6ghz_key_mgmt_mask(hdd_ctx->psoc,
13434 					       ALLOWED_KEYMGMT_6G_MASK);
13435 	}
13436 
13437 	return 0;
13438 }
13439 
13440 #ifdef WLAN_FEATURE_11BE_MLO
13441 static void wlan_hdd_set_listen_interval(struct hdd_context *hdd_ctx,
13442 					 struct hdd_adapter *adapter)
13443 {
13444 	struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
13445 	enum wlan_eht_mode eht_mode;
13446 	uint16_t max_simult_link_num;
13447 
13448 	ucfg_mlme_get_eht_mode(psoc, &eht_mode);
13449 	max_simult_link_num = wlan_mlme_get_sta_mlo_simultaneous_links(psoc);
13450 
13451 	if (eht_mode == WLAN_EHT_MODE_MLSR && max_simult_link_num == 0)
13452 		sme_set_listen_interval(hdd_ctx->mac_handle,
13453 					adapter->deflink->vdev_id);
13454 
13455 	hdd_debug("EHT mode: %d, max simultaneous link num: %d",
13456 		  eht_mode, max_simult_link_num);
13457 }
13458 #else
13459 static inline void wlan_hdd_set_listen_interval(struct hdd_context *hdd_ctx,
13460 					        struct hdd_adapter *adapter)
13461 {
13462 }
13463 #endif
13464 
13465 /**
13466  * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
13467  * vendor command
13468  *
13469  * @wiphy: wiphy device pointer
13470  * @wdev: wireless device pointer
13471  * @data: Vendor command data buffer
13472  * @data_len: Buffer length
13473  *
13474  * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
13475  *
13476  * Return: Error code.
13477  */
13478 static int
13479 __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
13480 		struct wireless_dev *wdev, const void *data, int data_len)
13481 {
13482 	struct net_device *dev = wdev->netdev;
13483 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13484 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
13485 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
13486 	int ret_val = 0;
13487 	uint8_t cfg_val = 0;
13488 	uint8_t ini_val = 0;
13489 	uint8_t set_val = 0;
13490 	struct sme_config_params *sme_config;
13491 	bool update_sme_cfg = false;
13492 	uint8_t tid = 0, ac;
13493 	uint16_t buff_size = 0;
13494 	mac_handle_t mac_handle;
13495 	QDF_STATUS status;
13496 	bool bval = false;
13497 	uint8_t value = 0;
13498 	uint8_t wmm_mode = 0;
13499 	uint32_t bss_max_idle_period = 0;
13500 	uint32_t cmd_id;
13501 	uint8_t link_id = 0xFF;
13502 	struct keep_alive_req keep_alive_req = {0};
13503 	struct set_wfatest_params wfa_param = {0};
13504 	struct wlan_hdd_link_info *link_info = adapter->deflink;
13505 	struct hdd_station_ctx *hdd_sta_ctx =
13506 			WLAN_HDD_GET_STATION_CTX_PTR(link_info);
13507 	uint8_t op_mode;
13508 
13509 	hdd_enter_dev(dev);
13510 
13511 	sme_config = qdf_mem_malloc(sizeof(*sme_config));
13512 	if (!sme_config)
13513 		return -ENOMEM;
13514 
13515 	mac_handle = hdd_ctx->mac_handle;
13516 	sme_get_config_param(mac_handle, sme_config);
13517 
13518 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13519 		hdd_err("Command not allowed in FTM mode");
13520 		ret_val = -EPERM;
13521 		goto send_err;
13522 	}
13523 
13524 	ret_val = wlan_hdd_validate_context(hdd_ctx);
13525 	if (ret_val)
13526 		goto send_err;
13527 
13528 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
13529 		hdd_err("Driver Modules are closed, can not start logger");
13530 		ret_val = -EINVAL;
13531 		goto send_err;
13532 	}
13533 
13534 	if (wlan_cfg80211_nla_parse(tb,
13535 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
13536 			data, data_len, wlan_hdd_wifi_test_config_policy)) {
13537 		hdd_err("invalid attr");
13538 		ret_val = -EINVAL;
13539 		goto send_err;
13540 	}
13541 
13542 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
13543 		cfg_val = nla_get_u8(tb[
13544 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
13545 			);
13546 		hdd_debug("set addba accept req from peer value %d", cfg_val);
13547 		ret_val = sme_set_addba_accept(mac_handle,
13548 					       link_info->vdev_id,
13549 					       cfg_val);
13550 		if (ret_val)
13551 			goto send_err;
13552 	}
13553 
13554 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
13555 		cfg_val = nla_get_u8(tb[
13556 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
13557 		hdd_debug("set HE MCS value 0x%0X", cfg_val);
13558 		ret_val = sme_update_he_mcs(mac_handle,
13559 					    link_info->vdev_id, cfg_val);
13560 		if (ret_val)
13561 			goto send_err;
13562 	}
13563 
13564 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
13565 		cfg_val = nla_get_u8(tb[
13566 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
13567 		if (!cfg_val) {
13568 			sme_config->csr_config.WMMSupportMode =
13569 				hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
13570 			hdd_debug("wmm is disabled");
13571 		} else {
13572 			status = ucfg_mlme_get_wmm_mode(hdd_ctx->psoc,
13573 							&wmm_mode);
13574 			if (!QDF_IS_STATUS_SUCCESS(status)) {
13575 				hdd_err("Get wmm_mode failed");
13576 				ret_val = -EINVAL;
13577 				goto send_err;
13578 			}
13579 			sme_config->csr_config.WMMSupportMode =
13580 				hdd_to_csr_wmm_mode(wmm_mode);
13581 			hdd_debug("using wmm default value");
13582 		}
13583 		update_sme_cfg = true;
13584 	}
13585 
13586 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
13587 		cfg_val = nla_get_u8(tb[
13588 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
13589 		if (cfg_val) {
13590 			/*Auto BA mode*/
13591 			set_val = HDD_BA_MODE_AUTO;
13592 			hdd_debug("BA operating mode is set to auto");
13593 		} else {
13594 			/*Manual BA mode*/
13595 			set_val = HDD_BA_MODE_MANUAL;
13596 			hdd_debug("BA operating mode is set to Manual");
13597 		}
13598 
13599 		op_mode = wlan_get_opmode_from_vdev_id(
13600 						hdd_ctx->pdev,
13601 						link_info->vdev_id);
13602 
13603 		sme_set_per_link_ba_mode(mac_handle, set_val);
13604 
13605 		if (!cfg_val) {
13606 			ret_val = wma_cli_set_command(
13607 				link_info->vdev_id,
13608 				wmi_vdev_param_amsdu_aggregation_size_optimization,
13609 				0, VDEV_CMD);
13610 		}
13611 	}
13612 
13613 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
13614 		cfg_val = nla_get_u8(tb[
13615 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
13616 			);
13617 		if (cfg_val > HE_FRAG_LEVEL1)
13618 			set_val = HE_FRAG_LEVEL1;
13619 		else
13620 			set_val = cfg_val;
13621 
13622 		hdd_debug("set HE fragmention to %d", set_val);
13623 		ret_val = sme_update_he_frag_supp(mac_handle,
13624 						  link_info->vdev_id,
13625 						  set_val);
13626 	}
13627 
13628 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
13629 		cfg_val = nla_get_u8(tb[
13630 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
13631 		sme_config->csr_config.wep_tkip_in_he = cfg_val;
13632 		hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
13633 
13634 		update_sme_cfg = true;
13635 	}
13636 
13637 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
13638 		if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
13639 			tid = nla_get_u8(tb[
13640 				QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
13641 		} else {
13642 			hdd_err("TID is not set for ADD/DEL BA cfg");
13643 			ret_val = -EINVAL;
13644 			goto send_err;
13645 		}
13646 		cfg_val = nla_get_u8(tb[
13647 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
13648 		if (cfg_val == QCA_WLAN_ADD_BA) {
13649 			if (tb[
13650 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
13651 				buff_size = nla_get_u16(tb[
13652 				QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
13653 			ret_val = sme_send_addba_req(mac_handle,
13654 						     link_info->vdev_id,
13655 						     tid, buff_size);
13656 		} else if (cfg_val == QCA_WLAN_DELETE_BA) {
13657 		} else {
13658 			hdd_err("Invalid BA session cfg");
13659 			ret_val = -EINVAL;
13660 			goto send_err;
13661 		}
13662 	} else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
13663 		uint32_t arg[2];
13664 		buff_size = nla_get_u16(tb[
13665 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
13666 		hdd_debug("set buff size to %d for all tids", buff_size);
13667 		ret_val = sme_set_ba_buff_size(mac_handle,
13668 					       link_info->vdev_id,
13669 					       buff_size);
13670 		if (ret_val)
13671 			goto send_err;
13672 
13673 		if (buff_size > 512)
13674 			/* Configure ADDBA req buffer size to 1024 */
13675 			set_val = HDD_BA_MODE_1024;
13676 		else if (buff_size > 256)
13677 			/* Configure ADDBA req buffer size to 512 */
13678 			set_val = HDD_BA_MODE_512;
13679 		else if (buff_size > 64)
13680 			/* Configure ADDBA req buffer size to 256 */
13681 			set_val = HDD_BA_MODE_256;
13682 		else
13683 			/* Configure ADDBA req buffer size to 64 */
13684 			set_val = HDD_BA_MODE_64;
13685 
13686 		sme_set_per_link_ba_mode(mac_handle, set_val);
13687 
13688 		ret_val = wma_cli_set_command(link_info->vdev_id,
13689 					      GEN_VDEV_PARAM_AMPDU,
13690 					      buff_size, GEN_CMD);
13691 
13692 		if (set_val == HDD_BA_MODE_512) {
13693 			arg[0] = 703;
13694 			arg[1] = 0;
13695 			ret_val = sme_send_unit_test_cmd(
13696 						adapter->deflink->vdev_id,
13697 						0x48, 2, arg);
13698 			if (ret_val)
13699 				hdd_err("Failed to set Full state BA support");
13700 		}
13701 	}
13702 
13703 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
13704 		int he_mcs_val;
13705 
13706 		if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
13707 			ac = nla_get_u8(tb[
13708 			     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
13709 		} else {
13710 			hdd_err("AC is not set for NO ACK policy config");
13711 			ret_val = -EINVAL;
13712 			goto send_err;
13713 		}
13714 		cfg_val = nla_get_u8(tb[
13715 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
13716 		hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
13717 		ret_val = sme_set_no_ack_policy(mac_handle,
13718 						link_info->vdev_id,
13719 						cfg_val, ac);
13720 		if (cfg_val) {
13721 			status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc,
13722 							     &bval);
13723 			if (!QDF_IS_STATUS_SUCCESS(status))
13724 				hdd_err("unable to get vht_enable2x2");
13725 			if (bval)
13726 				/*2x2 MCS 5 value*/
13727 				he_mcs_val = 0x45;
13728 			else
13729 				/*1x1 MCS 5 value*/
13730 				he_mcs_val = 0x25;
13731 
13732 			if (hdd_set_11ax_rate(adapter, he_mcs_val, NULL))
13733 				hdd_err("HE MCS set failed, MCS val %0x",
13734 						he_mcs_val);
13735 		} else {
13736 			if (hdd_set_11ax_rate(adapter, 0xFF, NULL))
13737 				hdd_err("disable fixed rate failed");
13738 		}
13739 	}
13740 
13741 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE;
13742 	if (tb[cmd_id]) {
13743 		cfg_val = nla_get_u8(tb[cmd_id]);
13744 		hdd_debug("Keep alive data type %d", cfg_val);
13745 		if (cfg_val == QCA_WLAN_KEEP_ALIVE_DATA) {
13746 			ret_val = hdd_set_grat_arp_keepalive(adapter);
13747 			if (ret_val) {
13748 				hdd_err("Keep alive data type set failed");
13749 				goto send_err;
13750 			}
13751 		} else {
13752 			if (cfg_val == QCA_WLAN_KEEP_ALIVE_MGMT)
13753 				keep_alive_req.packetType =
13754 						SIR_KEEP_ALIVE_MGMT_FRAME;
13755 			else
13756 				keep_alive_req.packetType =
13757 						SIR_KEEP_ALIVE_NULL_PKT;
13758 			ucfg_mlme_get_sta_keep_alive_period(
13759 						hdd_ctx->psoc,
13760 						&keep_alive_req.timePeriod);
13761 			keep_alive_req.sessionId = link_info->vdev_id;
13762 			status = sme_set_keep_alive(hdd_ctx->mac_handle,
13763 						    link_info->vdev_id,
13764 						    &keep_alive_req);
13765 			if (QDF_IS_STATUS_ERROR(status)) {
13766 				hdd_err("Failed to set keepalive");
13767 				ret_val = qdf_status_to_os_return(status);
13768 				goto send_err;
13769 			}
13770 		}
13771 	}
13772 
13773 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]) {
13774 		cfg_val = nla_get_u8(tb[
13775 				QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]);
13776 		hdd_debug("Set HE LTF to %d", cfg_val);
13777 		ret_val = sme_set_auto_rate_he_ltf(mac_handle,
13778 						   link_info->vdev_id,
13779 						   cfg_val);
13780 		if (ret_val)
13781 			sme_err("Failed to set auto rate HE LTF");
13782 
13783 		ret_val = wma_cli_set_command(link_info->vdev_id,
13784 					      wmi_vdev_param_set_he_ltf,
13785 					      cfg_val, VDEV_CMD);
13786 		if (ret_val)
13787 			goto send_err;
13788 	}
13789 
13790 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE;
13791 	if (tb[cmd_id]) {
13792 		cfg_val = nla_get_u8(tb[
13793 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]);
13794 		hdd_debug("Set Tx beamformee to %d", cfg_val);
13795 		ret_val = sme_update_tx_bfee_supp(mac_handle,
13796 						  link_info->vdev_id,
13797 						  cfg_val);
13798 		if (ret_val)
13799 			sme_err("Failed to update Tx beamformee support");
13800 
13801 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
13802 					      cfg_val, EHT_TX_BFEE_ENABLE,
13803 					      adapter->device_mode);
13804 		if (ret_val)
13805 			sme_err("Failed to set Tx beamformee cap");
13806 
13807 	}
13808 
13809 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS;
13810 	if (tb[cmd_id]) {
13811 		cfg_val = nla_get_u8(tb[cmd_id]);
13812 		ret_val = sme_update_he_capabilities(mac_handle,
13813 						     link_info->vdev_id,
13814 						     cfg_val, cmd_id);
13815 		if (ret_val)
13816 			sme_err("Failed to update HE cap");
13817 	}
13818 
13819 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT;
13820 	if (tb[cmd_id]) {
13821 		cfg_val = nla_get_u8(tb[cmd_id]);
13822 		ret_val = sme_update_he_capabilities(mac_handle,
13823 						     link_info->vdev_id,
13824 						     cfg_val, cmd_id);
13825 		if (ret_val)
13826 			sme_err("Failed to update HE cap");
13827 	}
13828 
13829 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]) {
13830 		cfg_val = nla_get_u8(tb[
13831 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS]);
13832 		status = ucfg_mlme_cfg_get_vht_tx_bfee_ant_supp(hdd_ctx->psoc,
13833 								&value);
13834 		if (!QDF_IS_STATUS_SUCCESS(status))
13835 			hdd_err("unable to get tx_bfee_ant_supp");
13836 
13837 		if (!cfg_in_range(CFG_VHT_BEAMFORMEE_ANT_SUPP, cfg_val)) {
13838 			hdd_err("NSTS %d not supported, supp_val %d", cfg_val,
13839 				value);
13840 			ret_val = -ENOTSUPP;
13841 			goto send_err;
13842 		}
13843 		hdd_debug("Set Tx beamformee NSTS to %d", cfg_val);
13844 		ret_val = sme_update_tx_bfee_nsts(hdd_ctx->mac_handle,
13845 						  link_info->vdev_id,
13846 						  cfg_val,
13847 						  value);
13848 		if (ret_val)
13849 			sme_err("Failed to set Tx beamformee cap");
13850 
13851 	}
13852 
13853 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]) {
13854 		cfg_val = nla_get_u8(tb[
13855 				     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR]);
13856 		if (cfg_val) {
13857 			hdd_debug("Set HE mac padding dur to %d", cfg_val);
13858 			ret_val = sme_cli_set_command(
13859 					link_info->vdev_id,
13860 					wmi_vdev_param_mu_edca_fw_update_en,
13861 					0, VDEV_CMD);
13862 			if (ret_val)
13863 				hdd_err("MU_EDCA update disable failed");
13864 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
13865 			sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
13866 			if (sme_update_mu_edca_params(
13867 						hdd_ctx->mac_handle,
13868 						link_info->vdev_id))
13869 				hdd_err("Failed to send mu edca params");
13870 		} else {
13871 			ret_val = sme_cli_set_command(
13872 					link_info->vdev_id,
13873 					wmi_vdev_param_mu_edca_fw_update_en,
13874 					1, VDEV_CMD);
13875 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
13876 		}
13877 		ret_val = sme_update_he_trigger_frm_mac_pad(
13878 						    hdd_ctx->mac_handle,
13879 						    link_info->vdev_id,
13880 						    cfg_val);
13881 		if (ret_val)
13882 			hdd_err("Failed to set Trig frame mac padding cap");
13883 	}
13884 
13885 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]) {
13886 		cfg_val = nla_get_u8(tb[
13887 				     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA]);
13888 		if (cfg_val) {
13889 			ret_val = sme_cli_set_command(
13890 					link_info->vdev_id,
13891 					wmi_vdev_param_mu_edca_fw_update_en,
13892 					0, VDEV_CMD);
13893 			if (ret_val)
13894 				hdd_err("MU_EDCA update disable failed");
13895 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, true);
13896 			sme_set_he_mu_edca_def_cfg(hdd_ctx->mac_handle);
13897 			if (sme_update_mu_edca_params(
13898 						hdd_ctx->mac_handle,
13899 						link_info->vdev_id))
13900 				hdd_err("Failed to send mu edca params");
13901 		} else {
13902 			ret_val = sme_cli_set_command(
13903 					link_info->vdev_id,
13904 					wmi_vdev_param_mu_edca_fw_update_en,
13905 					1, VDEV_CMD);
13906 			sme_set_usr_cfg_mu_edca(hdd_ctx->mac_handle, false);
13907 		}
13908 	}
13909 
13910 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]) {
13911 		cfg_val = nla_get_u8(tb[
13912 				     QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP]);
13913 		ret_val = sme_update_he_om_ctrl_supp(hdd_ctx->mac_handle,
13914 						     link_info->vdev_id,
13915 						     cfg_val);
13916 	}
13917 
13918 	cmd_id =
13919 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA;
13920 	if (tb[cmd_id]) {
13921 		cfg_val = nla_get_u8(tb[cmd_id]);
13922 		if (cfg_val)
13923 			status = ucfg_mlme_set_scan_probe_unicast_ra(
13924 							hdd_ctx->psoc, true);
13925 		else
13926 			status = ucfg_mlme_set_scan_probe_unicast_ra(
13927 							hdd_ctx->psoc, false);
13928 		if (!QDF_IS_STATUS_SUCCESS(status))
13929 			hdd_err("unable to set unicat probe ra cfg");
13930 	}
13931 
13932 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OMI_TX;
13933 	if (tb[cmd_id]) {
13934 		struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_OMI_MAX + 1];
13935 		struct nlattr *curr_attr;
13936 		int tmp, rc;
13937 		struct omi_ctrl_tx omi_data = {0};
13938 
13939 		nla_for_each_nested(curr_attr, tb[cmd_id], tmp) {
13940 			rc = wlan_cfg80211_nla_parse(
13941 					tb2, QCA_WLAN_VENDOR_ATTR_OMI_MAX,
13942 					nla_data(curr_attr),
13943 					nla_len(curr_attr),
13944 					qca_wlan_vendor_attr_omi_tx_policy);
13945 			if (rc) {
13946 				hdd_err("Invalid ATTR");
13947 				goto send_err;
13948 			}
13949 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW;
13950 			if (tb2[cmd_id]) {
13951 				cfg_val = nla_get_u8(tb2[cmd_id]);
13952 				ret_val = sme_set_he_om_ctrl_param(
13953 						    hdd_ctx->mac_handle,
13954 						    link_info->vdev_id,
13955 						    cmd_id, cfg_val);
13956 			}
13957 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS;
13958 			if (tb2[cmd_id]) {
13959 				cfg_val = nla_get_u8(tb2[cmd_id]);
13960 				ret_val = sme_set_he_om_ctrl_param(
13961 						    hdd_ctx->mac_handle,
13962 						    link_info->vdev_id,
13963 						    cmd_id, cfg_val);
13964 			}
13965 
13966 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE;
13967 			if (tb2[cmd_id]) {
13968 				cfg_val = nla_get_u8(tb2[cmd_id]);
13969 				ret_val = sme_set_he_om_ctrl_param(
13970 						    hdd_ctx->mac_handle,
13971 						    link_info->vdev_id,
13972 						    cmd_id, cfg_val);
13973 			}
13974 
13975 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS;
13976 			if (tb2[cmd_id]) {
13977 				cfg_val = nla_get_u8(tb2[cmd_id]);
13978 				ret_val = sme_set_he_om_ctrl_param(
13979 						    hdd_ctx->mac_handle,
13980 						    link_info->vdev_id,
13981 						    cmd_id, cfg_val);
13982 			}
13983 
13984 			cmd_id = QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE;
13985 			if (tb2[cmd_id]) {
13986 				cfg_val = nla_get_u8(tb2[cmd_id]);
13987 				ret_val = sme_set_he_om_ctrl_param(
13988 						    hdd_ctx->mac_handle,
13989 						    link_info->vdev_id,
13990 						    cmd_id, cfg_val);
13991 			}
13992 
13993 			cmd_id = QCA_WLAN_VENDOR_ATTR_EHT_OMI_RX_NSS_EXTN;
13994 			if (tb2[cmd_id]) {
13995 				cfg_val = nla_get_u8(tb2[cmd_id]);
13996 				hdd_debug("EHT OM ctrl Rx Nss %d", cfg_val);
13997 				omi_data.eht_rx_nss_ext = cfg_val;
13998 			}
13999 
14000 			cmd_id = QCA_WLAN_VENDOR_ATTR_EHT_OMI_CH_BW_EXTN;
14001 			if (tb2[cmd_id]) {
14002 				cfg_val = nla_get_u8(tb2[cmd_id]);
14003 				hdd_debug("Set EHT OM ctrl BW to %d", cfg_val);
14004 				omi_data.eht_ch_bw_ext = cfg_val;
14005 			}
14006 
14007 			cmd_id = QCA_WLAN_VENDOR_ATTR_EHT_OMI_TX_NSS_EXTN;
14008 			if (tb2[cmd_id]) {
14009 				cfg_val = nla_get_u8(tb2[cmd_id]);
14010 				hdd_debug("EHT OM ctrl Tx Nss %d", cfg_val);
14011 				omi_data.eht_tx_nss_ext = cfg_val;
14012 			}
14013 		}
14014 
14015 		if (ret_val) {
14016 			sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
14017 			goto send_err;
14018 		}
14019 		ret_val = sme_send_he_om_ctrl_update(hdd_ctx->mac_handle,
14020 						     link_info->vdev_id,
14021 						     &omi_data);
14022 	}
14023 
14024 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG])
14025 		sme_reset_he_om_ctrl(hdd_ctx->mac_handle);
14026 
14027 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU;
14028 	if (tb[cmd_id]) {
14029 		int i;
14030 		enum wlan_eht_mode eht_mode;
14031 		uint8_t op_mode;
14032 
14033 		cfg_val = nla_get_u8(tb[cmd_id]);
14034 		ucfg_mlme_get_eht_mode(hdd_ctx->psoc, &eht_mode);
14035 		if (eht_mode == WLAN_EHT_MODE_MLMR ||
14036 		    eht_mode == WLAN_EHT_MODE_MLSR ||
14037 		    eht_mode == WLAN_EHT_MODE_EMLSR) {
14038 			for (i = 0; i < WLAN_MAX_VDEVS; i++) {
14039 				op_mode = wlan_get_opmode_from_vdev_id(
14040 						hdd_ctx->pdev, i);
14041 				if (op_mode != QDF_STA_MODE) {
14042 					hdd_debug("vdev_id %d is not STA", i);
14043 					continue;
14044 				}
14045 				hdd_debug("Tx SU PPDU enable %d, vdev_id %d",
14046 					  cfg_val, i);
14047 				if (cfg_val)
14048 					sme_config_su_ppdu_queue(i, true);
14049 				else
14050 					sme_config_su_ppdu_queue(i, false);
14051 			}
14052 		} else {
14053 			if (cfg_val)
14054 				sme_config_su_ppdu_queue(link_info->vdev_id,
14055 							 true);
14056 			else
14057 				sme_config_su_ppdu_queue(link_info->vdev_id,
14058 							 false);
14059 		}
14060 	}
14061 
14062 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT;
14063 	if (tb[cmd_id]) {
14064 		cfg_val = nla_get_u8(tb[cmd_id]);
14065 		hdd_debug("Configure 2G VHT support %d", cfg_val);
14066 		ucfg_mlme_set_vht_for_24ghz(hdd_ctx->psoc,
14067 					    (cfg_val ? true : false));
14068 	}
14069 
14070 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP;
14071 	if (tb[cmd_id]) {
14072 		cfg_val = nla_get_u8(tb[cmd_id]);
14073 		hdd_debug("Configure +HTC_HE support %d", cfg_val);
14074 		sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
14075 					  link_info->vdev_id,
14076 					  (cfg_val ? true : false));
14077 	}
14078 
14079 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX;
14080 	if (tb[cmd_id]) {
14081 		cfg_val = nla_get_u8(tb[cmd_id]);
14082 		hdd_debug("Configure Punctured preamble Rx %d", cfg_val);
14083 		ret_val = sme_update_he_capabilities(mac_handle,
14084 						     link_info->vdev_id,
14085 						     cfg_val, cmd_id);
14086 		if (ret_val)
14087 			sme_err("Failed to update HE cap");
14088 	}
14089 
14090 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS;
14091 	if (tb[cmd_id]) {
14092 		hdd_disable_runtime_pm_for_user(hdd_ctx);
14093 		cfg_val = nla_get_u8(tb[cmd_id]);
14094 		hdd_debug("Configure HE testbed defaults %d", cfg_val);
14095 		if (!cfg_val)
14096 			sme_reset_he_caps(hdd_ctx->mac_handle,
14097 					  link_info->vdev_id);
14098 		else
14099 			sme_set_he_testbed_def(hdd_ctx->mac_handle,
14100 					       link_info->vdev_id);
14101 	}
14102 
14103 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU;
14104 	if (tb[cmd_id]) {
14105 		cfg_val = nla_get_u8(tb[cmd_id]);
14106 		hdd_debug("Configure Action frame Tx in TB PPDU %d", cfg_val);
14107 		sme_config_action_tx_in_tb_ppdu(hdd_ctx->mac_handle,
14108 						link_info->vdev_id,
14109 						cfg_val);
14110 	}
14111 
14112 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP]) {
14113 		ret_val = hdd_test_config_twt_setup_session(adapter, tb);
14114 		if (ret_val)
14115 			goto send_err;
14116 	}
14117 
14118 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE]) {
14119 		ret_val = hdd_test_config_twt_terminate_session(adapter, tb);
14120 		if (ret_val)
14121 			goto send_err;
14122 	}
14123 
14124 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT;
14125 	if (tb[cmd_id]) {
14126 		cfg_val = nla_get_u8(tb[cmd_id]);
14127 		hdd_debug("twt_request: val %d", cfg_val);
14128 		ret_val = sme_update_he_twt_req_support(
14129 						hdd_ctx->mac_handle,
14130 						link_info->vdev_id,
14131 						cfg_val);
14132 	}
14133 
14134 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO;
14135 	if (tb[cmd_id]) {
14136 		cfg_val = nla_get_u8(tb[cmd_id]);
14137 		ini_val = cfg_get(hdd_ctx->psoc, CFG_HE_UL_MUMIMO);
14138 		hdd_debug("fullbw_ulmumimo: cfg %d, ini %d", cfg_val, ini_val);
14139 		if (cfg_val) {
14140 			switch (ini_val) {
14141 			case CFG_NO_SUPPORT_UL_MUMIMO:
14142 			case CFG_FULL_BW_SUPPORT_UL_MUMIMO:
14143 				cfg_val = CFG_FULL_BW_SUPPORT_UL_MUMIMO;
14144 				break;
14145 			case CFG_PARTIAL_BW_SUPPORT_UL_MUMIMO:
14146 			case CFG_FULL_PARTIAL_BW_SUPPORT_UL_MUMIMO:
14147 				cfg_val = CFG_FULL_PARTIAL_BW_SUPPORT_UL_MUMIMO;
14148 				break;
14149 			}
14150 		} else {
14151 			switch (ini_val) {
14152 			case CFG_NO_SUPPORT_UL_MUMIMO:
14153 			case CFG_FULL_BW_SUPPORT_UL_MUMIMO:
14154 				cfg_val = CFG_NO_SUPPORT_UL_MUMIMO;
14155 				break;
14156 			case CFG_PARTIAL_BW_SUPPORT_UL_MUMIMO:
14157 			case CFG_FULL_PARTIAL_BW_SUPPORT_UL_MUMIMO:
14158 				cfg_val = CFG_PARTIAL_BW_SUPPORT_UL_MUMIMO;
14159 				break;
14160 			}
14161 		}
14162 		ret_val = sme_update_he_full_ul_mumimo(
14163 						hdd_ctx->mac_handle,
14164 						link_info->vdev_id,
14165 						cfg_val);
14166 	}
14167 
14168 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX;
14169 	if (tb[cmd_id]) {
14170 		cfg_val = nla_get_u8(tb[cmd_id]);
14171 		hdd_debug("disable Tx cfg: val %d", cfg_val);
14172 		sme_set_cfg_disable_tx(hdd_ctx->mac_handle,
14173 				       link_info->vdev_id, cfg_val);
14174 	}
14175 
14176 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION;
14177 	if (tb[cmd_id]) {
14178 		cfg_val = nla_get_u8(tb[cmd_id]);
14179 		hdd_debug("pmf cfg: val %d", cfg_val);
14180 		sme_set_pmf_wep_cfg(hdd_ctx->mac_handle, cfg_val);
14181 	}
14182 
14183 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD;
14184 	if (tb[cmd_id]) {
14185 		cfg_val = nla_get_u16(tb[cmd_id]);
14186 		hdd_debug("bss max idle period %d", cfg_val);
14187 		sme_set_bss_max_idle_period(hdd_ctx->mac_handle, cfg_val);
14188 	}
14189 
14190 	cmd_id =
14191 	QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE;
14192 	if (tb[cmd_id]) {
14193 		cfg_val = nla_get_u8(tb[cmd_id]);
14194 		if (cfg_val)
14195 			ucfg_mlme_get_sta_keep_alive_period(
14196 							hdd_ctx->psoc,
14197 							&bss_max_idle_period);
14198 		hdd_debug("bss max idle period %d", bss_max_idle_period);
14199 		sme_set_bss_max_idle_period(hdd_ctx->mac_handle,
14200 					    bss_max_idle_period);
14201 	}
14202 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX;
14203 	if (tb[cmd_id]) {
14204 		hdd_info("Send disassoc mgmt frame");
14205 		sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
14206 					    link_info->vdev_id,
14207 					    hdd_sta_ctx->conn_info.bssid.bytes,
14208 					    1, false);
14209 	}
14210 
14211 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX;
14212 	if (tb[cmd_id]) {
14213 		cfg_val = nla_get_u8(tb[cmd_id]);
14214 		hdd_info("RU 242 tone Tx enable: %d", cfg_val);
14215 		sme_set_ru_242_tone_tx_cfg(hdd_ctx->mac_handle, cfg_val);
14216 		if (cfg_val)
14217 			hdd_update_channel_width(
14218 					link_info, eHT_CHANNEL_WIDTH_20MHZ,
14219 					WNI_CFG_CHANNEL_BONDING_MODE_DISABLE,
14220 					link_id, false);
14221 	}
14222 
14223 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE;
14224 	if (tb[cmd_id]) {
14225 		cfg_val = nla_get_u8(tb[cmd_id]);
14226 		hdd_debug("EU SU PPDU type Tx enable: %d", cfg_val);
14227 		if (cfg_val) {
14228 			hdd_update_channel_width(
14229 					link_info, eHT_CHANNEL_WIDTH_20MHZ,
14230 					WNI_CFG_CHANNEL_BONDING_MODE_DISABLE,
14231 					link_id, false);
14232 			hdd_set_tx_stbc(link_info, 0);
14233 			hdd_set_11ax_rate(adapter, 0x400, NULL);
14234 			status = wma_cli_set_command(
14235 					link_info->vdev_id,
14236 					wmi_vdev_param_he_range_ext,
14237 					1, VDEV_CMD);
14238 			if (QDF_IS_STATUS_ERROR(status))
14239 				hdd_err("failed to set HE_RANGE_EXT, %d",
14240 					status);
14241 			status = wma_cli_set_command(
14242 					link_info->vdev_id,
14243 					wmi_vdev_param_non_data_he_range_ext,
14244 					1, VDEV_CMD);
14245 			if (QDF_IS_STATUS_ERROR(status))
14246 				hdd_err("fail to set NON_DATA_HE_RANGE_EXT %d",
14247 					status);
14248 		} else {
14249 			hdd_update_channel_width(
14250 					link_info, eHT_CHANNEL_WIDTH_160MHZ,
14251 					WNI_CFG_CHANNEL_BONDING_MODE_ENABLE,
14252 					link_id, false);
14253 			hdd_set_tx_stbc(link_info, 1);
14254 			hdd_set_11ax_rate(adapter, 0xFFFF, NULL);
14255 			status = wma_cli_set_command(
14256 					link_info->vdev_id,
14257 					wmi_vdev_param_he_range_ext,
14258 					0, VDEV_CMD);
14259 			if (QDF_IS_STATUS_ERROR(status))
14260 				hdd_err("failed to set HE_RANGE_EXT, %d",
14261 					status);
14262 			status = wma_cli_set_command(
14263 					link_info->vdev_id,
14264 					wmi_vdev_param_non_data_he_range_ext,
14265 					0, VDEV_CMD);
14266 			if (QDF_IS_STATUS_ERROR(status))
14267 				hdd_err("fail to set NON_DATA_HE_RANGE_EXT %d",
14268 					status);
14269 		}
14270 
14271 	}
14272 
14273 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED;
14274 	if (tb[cmd_id]) {
14275 		wfa_param.vdev_id = link_info->vdev_id;
14276 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14277 
14278 		if (wfa_param.value < RSNXE_DEFAULT ||
14279 		    wfa_param.value > RSNXE_OVERRIDE_2) {
14280 			hdd_debug("Invalid RSNXE override %d", wfa_param.value);
14281 			goto send_err;
14282 		}
14283 		wfa_param.cmd = WFA_CONFIG_RXNE;
14284 		hdd_info("send wfa test config RXNE used %d", wfa_param.value);
14285 
14286 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14287 						&wfa_param);
14288 	}
14289 
14290 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA;
14291 	if (tb[cmd_id]) {
14292 		wfa_param.vdev_id = link_info->vdev_id;
14293 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14294 
14295 		if (wfa_param.value != CSA_DEFAULT &&
14296 		    wfa_param.value != CSA_IGNORE) {
14297 			hdd_debug("Invalid CSA config %d", wfa_param.value);
14298 			goto send_err;
14299 		}
14300 		wfa_param.cmd = WFA_CONFIG_CSA;
14301 		hdd_info("send wfa test config CSA used %d", wfa_param.value);
14302 
14303 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14304 						&wfa_param);
14305 	}
14306 
14307 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE;
14308 	if (tb[cmd_id]) {
14309 		ret_val = hdd_test_config_6ghz_security_test_mode(hdd_ctx,
14310 								  tb[cmd_id]);
14311 		if (ret_val)
14312 			goto send_err;
14313 	}
14314 
14315 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE;
14316 	if (tb[cmd_id]) {
14317 		struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX + 1];
14318 
14319 		wfa_param.vdev_id = link_info->vdev_id;
14320 		wfa_param.cmd = WFA_CONFIG_OCV;
14321 		if (wlan_cfg80211_nla_parse_nested(
14322 				tb2, QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX,
14323 				tb[cmd_id], wlan_oci_override_policy)) {
14324 			hdd_debug("Failed to parse OCI override");
14325 			goto send_err;
14326 		}
14327 
14328 		if (!(tb2[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE] &&
14329 		      tb2[QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY])) {
14330 			hdd_debug("Invalid ATTR FRAME_TYPE/FREQUENCY");
14331 			goto send_err;
14332 		}
14333 
14334 		wfa_param.ocv_param = qdf_mem_malloc(
14335 				sizeof(struct ocv_wfatest_params));
14336 		if (!wfa_param.ocv_param) {
14337 			hdd_err("Failed to alloc memory for ocv param");
14338 			goto send_err;
14339 		}
14340 
14341 		cmd_id = QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE;
14342 		switch (nla_get_u8(tb2[cmd_id])) {
14343 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ:
14344 			wfa_param.ocv_param->frame_type =
14345 				WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_SAQUERY_REQ;
14346 			break;
14347 
14348 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP:
14349 			wfa_param.ocv_param->frame_type =
14350 				WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_SAQUERY_RSP;
14351 			break;
14352 
14353 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ:
14354 			wfa_param.ocv_param->frame_type =
14355 				WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_FT_REASSOC_REQ;
14356 			break;
14357 
14358 		case QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FILS_REASSOC_REQ:
14359 			wfa_param.ocv_param->frame_type =
14360 			WMI_HOST_WFA_CONFIG_OCV_FRMTYPE_FILS_REASSOC_REQ;
14361 			break;
14362 
14363 		default:
14364 			hdd_debug("Invalid frame type for ocv test config %d",
14365 				  nla_get_u8(tb2[cmd_id]));
14366 			qdf_mem_free(wfa_param.ocv_param);
14367 				goto send_err;
14368 		}
14369 
14370 		cmd_id = QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY;
14371 		wfa_param.ocv_param->freq = nla_get_u32(tb2[cmd_id]);
14372 
14373 		if (!WLAN_REG_IS_24GHZ_CH_FREQ(wfa_param.ocv_param->freq) &&
14374 		    !WLAN_REG_IS_5GHZ_CH_FREQ(wfa_param.ocv_param->freq) &&
14375 		    !WLAN_REG_IS_6GHZ_CHAN_FREQ(wfa_param.ocv_param->freq)) {
14376 			hdd_debug("Invalid Freq %d", wfa_param.ocv_param->freq);
14377 			qdf_mem_free(wfa_param.ocv_param);
14378 			goto send_err;
14379 		}
14380 
14381 		hdd_info("send wfa test config OCV frame type %d freq %d",
14382 			 wfa_param.ocv_param->frame_type,
14383 			 wfa_param.ocv_param->freq);
14384 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14385 						&wfa_param);
14386 		qdf_mem_free(wfa_param.ocv_param);
14387 	}
14388 
14389 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT;
14390 	if (tb[cmd_id]) {
14391 		wfa_param.vdev_id = link_info->vdev_id;
14392 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14393 
14394 		if (wfa_param.value != SA_QUERY_TIMEOUT_DEFAULT &&
14395 		    wfa_param.value != SA_QUERY_TIMEOUT_IGNORE) {
14396 			hdd_debug("Invalid SA query timeout config %d",
14397 				  wfa_param.value);
14398 			goto send_err;
14399 		}
14400 		wfa_param.cmd = WFA_CONFIG_SA_QUERY;
14401 		hdd_info("send wfa test config SAquery %d", wfa_param.value);
14402 
14403 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14404 						&wfa_param);
14405 	}
14406 
14407 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX;
14408 	if (tb[cmd_id] && adapter->device_mode == QDF_SAP_MODE) {
14409 		wfa_param.vdev_id = link_info->vdev_id;
14410 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14411 
14412 		if (!(wfa_param.value == FILS_DISCV_FRAMES_DISABLE ||
14413 		      wfa_param.value == FILS_DISCV_FRAMES_ENABLE)) {
14414 			hdd_debug("Invalid FILS_DISCV_FRAMES config %d",
14415 				  wfa_param.value);
14416 			goto send_err;
14417 		}
14418 		wfa_param.cmd = WFA_FILS_DISCV_FRAMES;
14419 		hdd_info("send wfa FILS_DISCV_FRAMES TX config %d",
14420 			 wfa_param.value);
14421 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14422 						&wfa_param);
14423 	}
14424 
14425 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE;
14426 	if (tb[cmd_id]) {
14427 		wfa_param.vdev_id = link_info->vdev_id;
14428 		wfa_param.value = nla_get_u8(tb[cmd_id]);
14429 
14430 		if (!(wfa_param.value == H2E_RSNXE_DEFAULT ||
14431 		      wfa_param.value == H2E_RSNXE_IGNORE)) {
14432 			hdd_debug("Invalid RSNXE_IGNORE config %d",
14433 				  wfa_param.value);
14434 			goto send_err;
14435 		}
14436 		wfa_param.cmd = WFA_IGNORE_H2E_RSNXE;
14437 		hdd_info("send wfa WFA_IGNORE_H2E_RSNXE config %d",
14438 			 wfa_param.value);
14439 		ret_val = ucfg_send_wfatest_cmd(link_info->vdev,
14440 						&wfa_param);
14441 	}
14442 
14443 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_11BE_EMLSR_MODE;
14444 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14445 		cfg_val = nla_get_u8(tb[cmd_id]);
14446 
14447 		ret_val = hdd_test_config_emlsr_mode(hdd_ctx, cfg_val);
14448 	}
14449 
14450 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BEAMFORMER_PERIODIC_SOUNDING;
14451 	if (tb[cmd_id]) {
14452 		cfg_val = nla_get_u8(tb[cmd_id]);
14453 
14454 		set_val = cfg_val ? TX_BFER_NDP_PERIODICITY : 0;
14455 
14456 		ret_val = wma_cli_set_command(
14457 					link_info->vdev_id,
14458 					WMI_PDEV_PARAM_TXBF_SOUND_PERIOD_CMDID,
14459 					set_val, PDEV_CMD);
14460 	}
14461 
14462 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_80MHZ;
14463 	if (tb[cmd_id]) {
14464 		cfg_val = nla_get_u8(tb[cmd_id]);
14465 		hdd_debug("Configure Tx BF < 80 MHz: %d", cfg_val);
14466 
14467 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14468 					      cfg_val, EHT_TX_BFEE_SS_80MHZ,
14469 					      adapter->device_mode);
14470 		if (ret_val)
14471 			sme_err("Failed to update EHT Tx BFEE cap");
14472 	}
14473 
14474 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_160MHZ;
14475 	if (tb[cmd_id]) {
14476 		cfg_val = nla_get_u8(tb[cmd_id]);
14477 		hdd_debug("Configure Tx BF for 160 MHz: %d", cfg_val);
14478 
14479 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14480 					      cfg_val, EHT_TX_BFEE_SS_160MHZ,
14481 					      adapter->device_mode);
14482 		if (ret_val)
14483 			sme_err("Failed to update EHT Tx BFEE cap");
14484 	}
14485 
14486 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_BEAMFORMEE_SS_320MHZ;
14487 	if (tb[cmd_id]) {
14488 		cfg_val = nla_get_u8(tb[cmd_id]);
14489 		hdd_debug("Configure Tx BF for 320 MHz: %d", cfg_val);
14490 
14491 		ret_val = sme_update_eht_caps(mac_handle, link_info->vdev_id,
14492 					      cfg_val, EHT_TX_BFEE_SS_320MHZ,
14493 					      adapter->device_mode);
14494 		if (ret_val)
14495 			sme_err("Failed to update EHT Tx BFEE cap");
14496 	}
14497 
14498 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EXCLUDE_STA_PROF_IN_PROBE_REQ;
14499 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14500 		cfg_val = nla_get_u8(tb[cmd_id]);
14501 
14502 		if (cfg_val) {
14503 			wlan_vdev_obj_lock(link_info->vdev);
14504 			wlan_vdev_mlme_cap_set(
14505 					link_info->vdev,
14506 					WLAN_VDEV_C_EXCL_STA_PROF_PRB_REQ);
14507 			wlan_vdev_obj_unlock(link_info->vdev);
14508 		} else {
14509 			wlan_vdev_obj_lock(link_info->vdev);
14510 			wlan_vdev_mlme_cap_clear(
14511 					link_info->vdev,
14512 					WLAN_VDEV_C_EXCL_STA_PROF_PRB_REQ);
14513 			wlan_vdev_obj_unlock(link_info->vdev);
14514 		}
14515 		hdd_debug("Sta profile in Probe req frame: %d", cfg_val);
14516 	}
14517 
14518 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_EHT_TESTBED_DEFAULTS;
14519 	if (tb[cmd_id]) {
14520 		cfg_val = nla_get_u8(tb[cmd_id]);
14521 		hdd_debug("Configure EHT testbed defaults %d", cfg_val);
14522 		if (!cfg_val)
14523 			sme_reset_eht_caps(hdd_ctx->mac_handle,
14524 					   link_info->vdev_id);
14525 		else
14526 			sme_set_eht_testbed_def(hdd_ctx->mac_handle,
14527 						link_info->vdev_id);
14528 
14529 		sme_set_vdev_ies_per_band(hdd_ctx->mac_handle,
14530 					  link_info->vdev_id,
14531 					  adapter->device_mode);
14532 	}
14533 
14534 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MCS;
14535 	if (tb[cmd_id]) {
14536 		cfg_val = nla_get_u8(tb[cmd_id]);
14537 		sme_update_eht_cap_mcs(hdd_ctx->mac_handle, link_info->vdev_id,
14538 				       cfg_val);
14539 		sme_set_vdev_ies_per_band(hdd_ctx->mac_handle,
14540 					  link_info->vdev_id,
14541 					  adapter->device_mode);
14542 	}
14543 
14544 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_TB_SOUNDING_FB_RL;
14545 	if (tb[cmd_id]) {
14546 		cfg_val = nla_get_u8(tb[cmd_id]);
14547 		hdd_debug("Configure TB sounding feedback rate limit: %d",
14548 			  cfg_val);
14549 
14550 		ret_val = sme_update_eht_caps(
14551 					mac_handle, link_info->vdev_id,
14552 					cfg_val,
14553 					EHT_TX_BFEE_SOUNDING_FEEDBACK_RATELIMIT,
14554 					adapter->device_mode);
14555 		if (ret_val)
14556 			sme_err("Failed to update EHT Tx BFEE cap");
14557 	}
14558 
14559 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_OM_CTRL_SUPPORT;
14560 	if (tb[cmd_id]) {
14561 		cfg_val = nla_get_u8(tb[cmd_id]);
14562 		hdd_debug("EHT OM control support: %d", cfg_val);
14563 
14564 		ret_val = sme_update_he_htc_he_supp(hdd_ctx->mac_handle,
14565 						    link_info->vdev_id,
14566 						    true);
14567 		if (ret_val)
14568 			hdd_err("Could not set htc_he");
14569 
14570 		ret_val = sme_update_eht_om_ctrl_supp(hdd_ctx->mac_handle,
14571 						      link_info->vdev_id,
14572 						      cfg_val);
14573 		if (ret_val)
14574 			hdd_err("Could not update EHT OM control fields");
14575 	}
14576 
14577 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EMLSR_PADDING_DELAY;
14578 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14579 		cfg_val = nla_get_u8(tb[cmd_id]);
14580 		hdd_debug("Configure EMLSR padding delay subfield to %d",
14581 			  cfg_val);
14582 		if (cfg_val)
14583 			wlan_mlme_cfg_set_emlsr_pad_delay(hdd_ctx->psoc,
14584 							  cfg_val);
14585 	}
14586 
14587 	cmd_id =  QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FORCE_MLO_POWER_SAVE_BCN_PERIOD;
14588 	if (tb[cmd_id] && adapter->device_mode == QDF_STA_MODE) {
14589 		uint32_t bitmap = 0;
14590 		uint32_t vdev_id, idx;
14591 
14592 		cfg_val = nla_get_u8(tb[cmd_id]);
14593 		hdd_debug("Send vdev pause on ML sta vdev for %d beacon periods",
14594 			  cfg_val);
14595 		bitmap = policy_mgr_get_active_vdev_bitmap(hdd_ctx->psoc);
14596 		for (idx = 0; idx < 32; idx++) {
14597 			if (bitmap & (1 << idx)) {
14598 				vdev_id = idx;
14599 				ret_val = sme_send_vdev_pause_for_bcn_period(
14600 							mac_handle,
14601 							vdev_id, cfg_val);
14602 				if (ret_val)
14603 					hdd_err("Failed to send vdev pause");
14604 			}
14605 		}
14606 	}
14607 
14608 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_STR_TX;
14609 	if (tb[cmd_id]) {
14610 		uint32_t arg[2];
14611 
14612 		hdd_debug("Send EHT MLO STR TX indication to FW");
14613 		arg[0] = 676;
14614 		arg[1] = 1;
14615 
14616 		ret_val = sme_send_unit_test_cmd(link_info->vdev_id,
14617 						 0x48, 2, arg);
14618 
14619 		if (ret_val)
14620 			hdd_err("Failed to send STR TX indication");
14621 	}
14622 
14623 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_LINK_POWER_SAVE;
14624 	if (tb[cmd_id]) {
14625 		struct nlattr *curr_attr;
14626 		int len;
14627 		uint8_t link_id, timeout = 0, num_links = 0;
14628 		bool allow_ps = true;
14629 
14630 		nla_for_each_nested(curr_attr, tb[cmd_id], len) {
14631 			if (nla_len(curr_attr) != sizeof(uint8_t)) {
14632 				hdd_err("len is not correct for idx %d",
14633 					num_links);
14634 				goto send_err;
14635 			}
14636 			link_id = nla_get_u8(curr_attr);
14637 			hdd_debug("link id[%d]: %d", num_links, link_id);
14638 			wlan_hdd_set_mlo_ps(adapter, allow_ps, timeout,
14639 					    link_id);
14640 			num_links++;
14641 		}
14642 
14643 		wlan_hdd_set_listen_interval(hdd_ctx, adapter);
14644 	}
14645 
14646 	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MLD_ID_ML_PROBE_REQ;
14647 	if (tb[cmd_id]) {
14648 		cfg_val = nla_get_u8(tb[cmd_id]);
14649 		hdd_debug("MLD ID in ML probe request: %d", cfg_val);
14650 		ret_val = ucfg_mlme_set_eht_mld_id(hdd_ctx->psoc, cfg_val);
14651 		if (ret_val)
14652 			hdd_err("Failed to set MLD ID");
14653 	}
14654 
14655 	if (update_sme_cfg)
14656 		sme_update_config(mac_handle, sme_config);
14657 
14658 send_err:
14659 	qdf_mem_free(sme_config);
14660 
14661 	return ret_val;
14662 }
14663 
14664 /**
14665  * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
14666  * vendor command
14667  *
14668  * @wiphy: wiphy device pointer
14669  * @wdev: wireless device pointer
14670  * @data: Vendor command data buffer
14671  * @data_len: Buffer length
14672  *
14673  * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
14674  *
14675  * Return: EOK or other error codes.
14676  */
14677 static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
14678 		struct wireless_dev *wdev, const void *data, int data_len)
14679 {
14680 	int errno;
14681 	struct osif_vdev_sync *vdev_sync;
14682 
14683 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
14684 	if (errno)
14685 		return errno;
14686 
14687 	errno = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
14688 							 data, data_len);
14689 
14690 	osif_vdev_sync_op_stop(vdev_sync);
14691 
14692 	return errno;
14693 }
14694 
14695 const struct nla_policy qca_wlan_vendor_wifi_logger_start_policy[
14696 		QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
14697 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
14698 		= {.type = NLA_U32 },
14699 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
14700 		= {.type = NLA_U32 },
14701 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
14702 		= {.type = NLA_U32 },
14703 };
14704 
14705 /**
14706  * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
14707  * or disable the collection of packet statistics from the firmware
14708  * @wiphy:    WIPHY structure pointer
14709  * @wdev:     Wireless device structure pointer
14710  * @data:     Pointer to the data received
14711  * @data_len: Length of the data received
14712  *
14713  * This function enables or disables the collection of packet statistics from
14714  * the firmware
14715  *
14716  * Return: 0 on success and errno on failure
14717  */
14718 static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
14719 		struct wireless_dev *wdev,
14720 		const void *data,
14721 		int data_len)
14722 {
14723 	QDF_STATUS status;
14724 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
14725 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
14726 	struct sir_wifi_start_log start_log = { 0 };
14727 	mac_handle_t mac_handle;
14728 
14729 	hdd_enter_dev(wdev->netdev);
14730 
14731 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
14732 		hdd_err("Command not allowed in FTM mode");
14733 		return -EPERM;
14734 	}
14735 
14736 	status = wlan_hdd_validate_context(hdd_ctx);
14737 	if (status)
14738 		return status;
14739 
14740 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
14741 		hdd_err("Driver Modules are closed, can not start logger");
14742 		return -EINVAL;
14743 	}
14744 
14745 	if (wlan_cfg80211_nla_parse(tb,
14746 				    QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
14747 				    data, data_len,
14748 				    qca_wlan_vendor_wifi_logger_start_policy)) {
14749 		hdd_err("Invalid attribute");
14750 		return -EINVAL;
14751 	}
14752 
14753 	/* Parse and fetch ring id */
14754 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
14755 		hdd_err("attr ATTR failed");
14756 		return -EINVAL;
14757 	}
14758 	start_log.ring_id = nla_get_u32(
14759 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
14760 	hdd_debug("Ring ID=%d", start_log.ring_id);
14761 
14762 	/* Parse and fetch verbose level */
14763 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
14764 		hdd_err("attr verbose_level failed");
14765 		return -EINVAL;
14766 	}
14767 	start_log.verbose_level = nla_get_u32(
14768 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
14769 	hdd_debug("verbose_level=%d", start_log.verbose_level);
14770 
14771 	/* Parse and fetch flag */
14772 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
14773 		hdd_err("attr flag failed");
14774 		return -EINVAL;
14775 	}
14776 	start_log.is_iwpriv_command = nla_get_u32(
14777 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
14778 
14779 	start_log.user_triggered = 1;
14780 
14781 	/* size is buff size which can be set using iwpriv command*/
14782 	start_log.size = 0;
14783 	start_log.is_pktlog_buff_clear = false;
14784 
14785 	cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
14786 
14787 	if (start_log.ring_id == RING_ID_WAKELOCK) {
14788 		/* Start/stop wakelock events */
14789 		if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
14790 			cds_set_wakelock_logging(true);
14791 		else
14792 			cds_set_wakelock_logging(false);
14793 		return 0;
14794 	}
14795 
14796 	if (start_log.ring_id == RING_ID_PER_PACKET_STATS) {
14797 		if (hdd_ctx->is_pktlog_enabled &&
14798 		    (start_log.verbose_level == WLAN_LOG_LEVEL_ACTIVE))
14799 			return 0;
14800 
14801 		if ((!hdd_ctx->is_pktlog_enabled) &&
14802 		    (start_log.verbose_level != WLAN_LOG_LEVEL_ACTIVE))
14803 			return 0;
14804 	}
14805 
14806 	mac_handle = hdd_ctx->mac_handle;
14807 	status = sme_wifi_start_logger(mac_handle, start_log);
14808 	if (!QDF_IS_STATUS_SUCCESS(status)) {
14809 		hdd_err("sme_wifi_start_logger failed(err=%d)",
14810 				status);
14811 		return -EINVAL;
14812 	}
14813 
14814 	if (start_log.ring_id == RING_ID_PER_PACKET_STATS) {
14815 		if (start_log.verbose_level == WLAN_LOG_LEVEL_ACTIVE)
14816 			hdd_ctx->is_pktlog_enabled = true;
14817 		else
14818 			hdd_ctx->is_pktlog_enabled = false;
14819 	}
14820 
14821 	return 0;
14822 }
14823 
14824 /**
14825  * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
14826  * or disable the collection of packet statistics from the firmware
14827  * @wiphy:    WIPHY structure pointer
14828  * @wdev:     Wireless device structure pointer
14829  * @data:     Pointer to the data received
14830  * @data_len: Length of the data received
14831  *
14832  * This function is used to enable or disable the collection of packet
14833  * statistics from the firmware
14834  *
14835  * Return: 0 on success and errno on failure
14836  */
14837 static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
14838 		struct wireless_dev *wdev,
14839 		const void *data,
14840 		int data_len)
14841 {
14842 	struct osif_psoc_sync *psoc_sync;
14843 	int errno;
14844 
14845 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
14846 	if (errno)
14847 		return errno;
14848 
14849 	errno = __wlan_hdd_cfg80211_wifi_logger_start(wiphy, wdev,
14850 						      data, data_len);
14851 
14852 	osif_psoc_sync_op_stop(psoc_sync);
14853 
14854 	return errno;
14855 }
14856 
14857 const struct nla_policy qca_wlan_vendor_wifi_logger_get_ring_data_policy[
14858 		QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
14859 	[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
14860 		= {.type = NLA_U32 },
14861 };
14862 
14863 /**
14864  * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
14865  * @wiphy:    WIPHY structure pointer
14866  * @wdev:     Wireless device structure pointer
14867  * @data:     Pointer to the data received
14868  * @data_len: Length of the data received
14869  *
14870  * This function is used to flush or retrieve the per packet statistics from
14871  * the driver
14872  *
14873  * Return: 0 on success and errno on failure
14874  */
14875 static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
14876 		struct wireless_dev *wdev,
14877 		const void *data,
14878 		int data_len)
14879 {
14880 	QDF_STATUS status;
14881 	uint32_t ring_id;
14882 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
14883 	struct nlattr *tb
14884 		[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
14885 
14886 	hdd_enter();
14887 
14888 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
14889 		hdd_err("Command not allowed in FTM mode");
14890 		return -EPERM;
14891 	}
14892 
14893 	status = wlan_hdd_validate_context(hdd_ctx);
14894 	if (status)
14895 		return status;
14896 
14897 	if (wlan_cfg80211_nla_parse(tb,
14898 			    QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
14899 			    data, data_len,
14900 			    qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
14901 		hdd_err("Invalid attribute");
14902 		return -EINVAL;
14903 	}
14904 
14905 	/* Parse and fetch ring id */
14906 	if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
14907 		hdd_err("attr ATTR failed");
14908 		return -EINVAL;
14909 	}
14910 
14911 	ring_id = nla_get_u32(
14912 			tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
14913 
14914 	if (ring_id == RING_ID_PER_PACKET_STATS) {
14915 		wlan_logging_set_per_pkt_stats();
14916 		hdd_debug("Flushing/Retrieving packet stats");
14917 	} else if (ring_id == RING_ID_DRIVER_DEBUG) {
14918 		/*
14919 		 * As part of DRIVER ring ID, flush both driver and fw logs.
14920 		 * For other Ring ID's driver doesn't have any rings to flush
14921 		 */
14922 		hdd_debug("Bug report triggered by framework");
14923 
14924 		status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
14925 				WLAN_LOG_INDICATOR_FRAMEWORK,
14926 				WLAN_LOG_REASON_CODE_UNUSED,
14927 				false, false);
14928 		if (QDF_STATUS_SUCCESS != status) {
14929 			hdd_err("Failed to trigger bug report");
14930 			return -EINVAL;
14931 		}
14932 		status = wlan_logging_wait_for_flush_log_completion();
14933 		if (!QDF_IS_STATUS_SUCCESS(status)) {
14934 			hdd_err("wait for flush log timed out");
14935 			return qdf_status_to_os_return(status);
14936 		}
14937 	} else {
14938 		wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
14939 					   WLAN_LOG_INDICATOR_FRAMEWORK,
14940 					   WLAN_LOG_REASON_CODE_UNUSED,
14941 					   ring_id);
14942 	}
14943 	return 0;
14944 }
14945 
14946 /**
14947  * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
14948  * @wiphy:    WIPHY structure pointer
14949  * @wdev:     Wireless device structure pointer
14950  * @data:     Pointer to the data received
14951  * @data_len: Length of the data received
14952  *
14953  * This function is used to flush or retrieve the per packet statistics from
14954  * the driver
14955  *
14956  * Return: 0 on success and errno on failure
14957  */
14958 static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
14959 		struct wireless_dev *wdev,
14960 		const void *data,
14961 		int data_len)
14962 {
14963 	struct osif_psoc_sync *psoc_sync;
14964 	int errno;
14965 
14966 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
14967 	if (errno)
14968 		return errno;
14969 
14970 	errno = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy, wdev,
14971 							      data, data_len);
14972 
14973 	osif_psoc_sync_op_stop(psoc_sync);
14974 
14975 	return errno;
14976 }
14977 
14978 #ifdef WLAN_FEATURE_OFFLOAD_PACKETS
14979 /**
14980  * hdd_map_req_id_to_pattern_id() - map request id to pattern id
14981  * @hdd_ctx: HDD context
14982  * @request_id: [input] request id
14983  * @pattern_id: [output] pattern id
14984  *
14985  * This function loops through request id to pattern id array
14986  * if the slot is available, store the request id and return pattern id
14987  * if entry exists, return the pattern id
14988  *
14989  * Return: 0 on success and errno on failure
14990  */
14991 static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
14992 					  uint32_t request_id,
14993 					  uint8_t *pattern_id)
14994 {
14995 	uint32_t i;
14996 
14997 	mutex_lock(&hdd_ctx->op_ctx.op_lock);
14998 	for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
14999 		if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
15000 			hdd_ctx->op_ctx.op_table[i].request_id = request_id;
15001 			*pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
15002 			mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15003 			return 0;
15004 		} else if (hdd_ctx->op_ctx.op_table[i].request_id ==
15005 					request_id) {
15006 			*pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
15007 			mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15008 			return 0;
15009 		}
15010 	}
15011 	mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15012 	return -ENOBUFS;
15013 }
15014 
15015 /**
15016  * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
15017  * @hdd_ctx: HDD context
15018  * @request_id: [input] request id
15019  * @pattern_id: [output] pattern id
15020  *
15021  * This function loops through request id to pattern id array
15022  * reset request id to 0 (slot available again) and
15023  * return pattern id
15024  *
15025  * Return: 0 on success and errno on failure
15026  */
15027 static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
15028 					  uint32_t request_id,
15029 					  uint8_t *pattern_id)
15030 {
15031 	uint32_t i;
15032 
15033 	mutex_lock(&hdd_ctx->op_ctx.op_lock);
15034 	for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
15035 		if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
15036 			hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
15037 			*pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
15038 			mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15039 			return 0;
15040 		}
15041 	}
15042 	mutex_unlock(&hdd_ctx->op_ctx.op_lock);
15043 	return -EINVAL;
15044 }
15045 
15046 
15047 /*
15048  * define short names for the global vendor params
15049  * used by __wlan_hdd_cfg80211_offloaded_packets()
15050  */
15051 #define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
15052 #define PARAM_REQUEST_ID \
15053 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
15054 #define PARAM_CONTROL \
15055 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
15056 #define PARAM_IP_PACKET \
15057 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
15058 #define PARAM_SRC_MAC_ADDR \
15059 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
15060 #define PARAM_DST_MAC_ADDR \
15061 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
15062 #define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
15063 #define PARAM_PROTO_TYPE \
15064 		QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE
15065 
15066 const struct nla_policy offloaded_packet_policy[
15067 			QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX + 1] = {
15068 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL] = {
15069 			.type = NLA_U32},
15070 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID] = {.type = NLA_U32},
15071 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA] = {
15072 			.type = NLA_BINARY},
15073 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR] = {
15074 			.type = NLA_BINARY,
15075 			.len = QDF_MAC_ADDR_SIZE },
15076 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR] = {
15077 			.type = NLA_BINARY,
15078 			.len = QDF_MAC_ADDR_SIZE },
15079 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD] = {
15080 			.type = NLA_U32},
15081 	[QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE] = {
15082 			.type = NLA_U16},
15083 };
15084 
15085 /**
15086  * wlan_hdd_add_tx_ptrn() - add tx pattern
15087  * @adapter: adapter pointer
15088  * @hdd_ctx: hdd context
15089  * @tb: nl attributes
15090  *
15091  * This function reads the NL attributes and forms a AddTxPtrn message
15092  * posts it to SME.
15093  *
15094  */
15095 static int
15096 wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
15097 			struct nlattr **tb)
15098 {
15099 	struct sSirAddPeriodicTxPtrn *add_req;
15100 	QDF_STATUS status;
15101 	uint32_t request_id, len;
15102 	int32_t ret;
15103 	uint8_t pattern_id = 0;
15104 	struct qdf_mac_addr dst_addr;
15105 	uint16_t eth_type = htons(ETH_P_IP);
15106 	mac_handle_t mac_handle;
15107 
15108 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
15109 		hdd_err("Not in Connected state!");
15110 		return -ENOTSUPP;
15111 	}
15112 
15113 	add_req = qdf_mem_malloc(sizeof(*add_req));
15114 	if (!add_req)
15115 		return -ENOMEM;
15116 
15117 	/* Parse and fetch request Id */
15118 	if (!tb[PARAM_REQUEST_ID]) {
15119 		hdd_err("attr request id failed");
15120 		ret = -EINVAL;
15121 		goto fail;
15122 	}
15123 
15124 	request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
15125 	if (request_id == MAX_REQUEST_ID) {
15126 		hdd_err("request_id cannot be MAX");
15127 		ret = -EINVAL;
15128 		goto fail;
15129 	}
15130 	hdd_debug("Request Id: %u", request_id);
15131 
15132 	if (!tb[PARAM_PERIOD]) {
15133 		hdd_err("attr period failed");
15134 		ret = -EINVAL;
15135 		goto fail;
15136 	}
15137 
15138 	add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
15139 	hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
15140 	if (add_req->usPtrnIntervalMs == 0) {
15141 		hdd_err("Invalid interval zero, return failure");
15142 		ret = -EINVAL;
15143 		goto fail;
15144 	}
15145 
15146 	if (!tb[PARAM_SRC_MAC_ADDR]) {
15147 		hdd_err("attr source mac address failed");
15148 		ret = -EINVAL;
15149 		goto fail;
15150 	}
15151 	nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
15152 			QDF_MAC_ADDR_SIZE);
15153 	hdd_debug("input src mac address: "QDF_MAC_ADDR_FMT,
15154 			QDF_MAC_ADDR_REF(add_req->mac_address.bytes));
15155 
15156 	if (!qdf_is_macaddr_equal(&add_req->mac_address,
15157 				  &adapter->mac_addr)) {
15158 		hdd_err("input src mac address and connected ap bssid are different");
15159 		ret = -EINVAL;
15160 		goto fail;
15161 	}
15162 
15163 	if (!tb[PARAM_DST_MAC_ADDR]) {
15164 		hdd_err("attr dst mac address failed");
15165 		ret = -EINVAL;
15166 		goto fail;
15167 	}
15168 	nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
15169 	hdd_debug("input dst mac address: "QDF_MAC_ADDR_FMT,
15170 			QDF_MAC_ADDR_REF(dst_addr.bytes));
15171 
15172 	if (!tb[PARAM_IP_PACKET]) {
15173 		hdd_err("attr ip packet failed");
15174 		ret = -EINVAL;
15175 		goto fail;
15176 	}
15177 	add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
15178 	hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
15179 
15180 	if (add_req->ucPtrnSize < 0 ||
15181 		add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
15182 					ETH_HLEN)) {
15183 		hdd_err("Invalid IP packet len: %d",
15184 				add_req->ucPtrnSize);
15185 		ret = -EINVAL;
15186 		goto fail;
15187 	}
15188 
15189 	if (!tb[PARAM_PROTO_TYPE])
15190 		eth_type = htons(ETH_P_IP);
15191 	else
15192 		eth_type = htons(nla_get_u16(tb[PARAM_PROTO_TYPE]));
15193 
15194 	hdd_debug("packet proto type: %u", eth_type);
15195 
15196 	len = 0;
15197 	qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
15198 	len += QDF_MAC_ADDR_SIZE;
15199 	qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
15200 			QDF_MAC_ADDR_SIZE);
15201 	len += QDF_MAC_ADDR_SIZE;
15202 	qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
15203 	len += 2;
15204 
15205 	/*
15206 	 * This is the IP packet, add 14 bytes Ethernet (802.3) header
15207 	 * ------------------------------------------------------------
15208 	 * | 14 bytes Ethernet (802.3) header | IP header and payload |
15209 	 * ------------------------------------------------------------
15210 	 */
15211 	qdf_mem_copy(&add_req->ucPattern[len],
15212 			nla_data(tb[PARAM_IP_PACKET]),
15213 			add_req->ucPtrnSize);
15214 	add_req->ucPtrnSize += len;
15215 
15216 	ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
15217 	if (ret) {
15218 		hdd_err("req id to pattern id failed (ret=%d)", ret);
15219 		goto fail;
15220 	}
15221 	add_req->ucPtrnId = pattern_id;
15222 	hdd_debug("pattern id: %d", add_req->ucPtrnId);
15223 
15224 	mac_handle = hdd_ctx->mac_handle;
15225 	status = sme_add_periodic_tx_ptrn(mac_handle, add_req);
15226 	if (!QDF_IS_STATUS_SUCCESS(status)) {
15227 		hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
15228 		ret = qdf_status_to_os_return(status);
15229 		goto fail;
15230 	}
15231 
15232 	hdd_exit();
15233 
15234 fail:
15235 	qdf_mem_free(add_req);
15236 	return ret;
15237 }
15238 
15239 /**
15240  * wlan_hdd_del_tx_ptrn() - delete tx pattern
15241  * @adapter: adapter pointer
15242  * @hdd_ctx: hdd context
15243  * @tb: nl attributes
15244  *
15245  * This function reads the NL attributes and forms a DelTxPtrn message
15246  * posts it to SME.
15247  *
15248  */
15249 static int
15250 wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
15251 			struct nlattr **tb)
15252 {
15253 	struct sSirDelPeriodicTxPtrn *del_req;
15254 	QDF_STATUS status;
15255 	uint32_t request_id, ret;
15256 	uint8_t pattern_id = 0;
15257 	mac_handle_t mac_handle;
15258 
15259 	/* Parse and fetch request Id */
15260 	if (!tb[PARAM_REQUEST_ID]) {
15261 		hdd_err("attr request id failed");
15262 		return -EINVAL;
15263 	}
15264 	request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
15265 	if (request_id == MAX_REQUEST_ID) {
15266 		hdd_err("request_id cannot be MAX");
15267 		return -EINVAL;
15268 	}
15269 
15270 	ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
15271 	if (ret) {
15272 		hdd_err("req id to pattern id failed (ret=%d)", ret);
15273 		return -EINVAL;
15274 	}
15275 
15276 	del_req = qdf_mem_malloc(sizeof(*del_req));
15277 	if (!del_req)
15278 		return -ENOMEM;
15279 
15280 	qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
15281 	hdd_debug(QDF_MAC_ADDR_FMT,
15282 		  QDF_MAC_ADDR_REF(del_req->mac_address.bytes));
15283 	del_req->ucPtrnId = pattern_id;
15284 	hdd_debug("Request Id: %u Pattern id: %d",
15285 			 request_id, del_req->ucPtrnId);
15286 
15287 	mac_handle = hdd_ctx->mac_handle;
15288 	status = sme_del_periodic_tx_ptrn(mac_handle, del_req);
15289 	if (!QDF_IS_STATUS_SUCCESS(status)) {
15290 		hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
15291 		goto fail;
15292 	}
15293 
15294 	hdd_exit();
15295 	qdf_mem_free(del_req);
15296 	return 0;
15297 
15298 fail:
15299 	qdf_mem_free(del_req);
15300 	return -EINVAL;
15301 }
15302 
15303 
15304 /**
15305  * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
15306  * @wiphy: Pointer to wireless phy
15307  * @wdev: Pointer to wireless device
15308  * @data: Pointer to data
15309  * @data_len: Data length
15310  *
15311  * Return: 0 on success, negative errno on failure
15312  */
15313 static int
15314 __wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
15315 				     struct wireless_dev *wdev,
15316 				     const void *data,
15317 				     int data_len)
15318 {
15319 	struct net_device *dev = wdev->netdev;
15320 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15321 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15322 	struct nlattr *tb[PARAM_MAX + 1];
15323 	uint8_t control;
15324 	int ret;
15325 
15326 	hdd_enter_dev(dev);
15327 
15328 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15329 		hdd_err("Command not allowed in FTM mode");
15330 		return -EPERM;
15331 	}
15332 
15333 	ret = wlan_hdd_validate_context(hdd_ctx);
15334 	if (ret)
15335 		return ret;
15336 
15337 	if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
15338 		hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
15339 		return -ENOTSUPP;
15340 	}
15341 
15342 	if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len,
15343 				    offloaded_packet_policy)) {
15344 		hdd_err("Invalid ATTR");
15345 		return -EINVAL;
15346 	}
15347 
15348 	if (!tb[PARAM_CONTROL]) {
15349 		hdd_err("attr control failed");
15350 		return -EINVAL;
15351 	}
15352 	control = nla_get_u32(tb[PARAM_CONTROL]);
15353 	hdd_debug("Control: %d", control);
15354 
15355 	if (control == WLAN_START_OFFLOADED_PACKETS)
15356 		return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
15357 	if (control == WLAN_STOP_OFFLOADED_PACKETS)
15358 		return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
15359 
15360 	hdd_err("Invalid control: %d", control);
15361 	return -EINVAL;
15362 }
15363 
15364 /*
15365  * done with short names for the global vendor params
15366  * used by __wlan_hdd_cfg80211_offloaded_packets()
15367  */
15368 #undef PARAM_MAX
15369 #undef PARAM_REQUEST_ID
15370 #undef PARAM_CONTROL
15371 #undef PARAM_IP_PACKET
15372 #undef PARAM_SRC_MAC_ADDR
15373 #undef PARAM_DST_MAC_ADDR
15374 #undef PARAM_PERIOD
15375 #undef PARAM_PROTO_TYPE
15376 
15377 /**
15378  * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
15379  * @wiphy:    wiphy structure pointer
15380  * @wdev:     Wireless device structure pointer
15381  * @data:     Pointer to the data received
15382  * @data_len: Length of @data
15383  *
15384  * Return: 0 on success; errno on failure
15385  */
15386 static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
15387 						struct wireless_dev *wdev,
15388 						const void *data,
15389 						int data_len)
15390 {
15391 	int errno;
15392 	struct osif_vdev_sync *vdev_sync;
15393 
15394 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
15395 	if (errno)
15396 		return errno;
15397 
15398 	errno = __wlan_hdd_cfg80211_offloaded_packets(wiphy, wdev,
15399 						      data, data_len);
15400 
15401 	osif_vdev_sync_op_stop(vdev_sync);
15402 
15403 	return errno;
15404 }
15405 #endif
15406 
15407 #ifdef WLAN_NS_OFFLOAD
15408 const struct nla_policy ns_offload_set_policy[
15409 			QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
15410 	[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
15411 };
15412 
15413 /**
15414  * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
15415  * @wiphy: Pointer to wireless phy
15416  * @wdev: Pointer to wireless device
15417  * @data: Pointer to data
15418  * @data_len: Length of @data
15419  *
15420  * Return: 0 on success, negative errno on failure
15421  */
15422 static int
15423 __wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
15424 			struct wireless_dev *wdev,
15425 			const void *data, int data_len)
15426 {
15427 	int status;
15428 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
15429 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15430 	struct net_device *dev = wdev->netdev;
15431 	struct hdd_adapter *adapter =  WLAN_HDD_GET_PRIV_PTR(dev);
15432 	struct wlan_objmgr_vdev *vdev;
15433 
15434 	hdd_enter_dev(wdev->netdev);
15435 
15436 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15437 		hdd_err("Command not allowed in FTM mode");
15438 		return -EPERM;
15439 	}
15440 
15441 	status = wlan_hdd_validate_context(hdd_ctx);
15442 	if (0 != status)
15443 		return status;
15444 
15445 	if (!ucfg_pmo_is_ns_offloaded(hdd_ctx->psoc)) {
15446 		hdd_err("ND Offload not supported");
15447 		return -EINVAL;
15448 	}
15449 
15450 	if (!ucfg_pmo_is_active_mode_offloaded(hdd_ctx->psoc)) {
15451 		hdd_warn("Active mode offload is disabled");
15452 		return -EINVAL;
15453 	}
15454 
15455 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
15456 				    (struct nlattr *)data, data_len,
15457 				    ns_offload_set_policy)) {
15458 		hdd_err("nla_parse failed");
15459 		return -EINVAL;
15460 	}
15461 
15462 	if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
15463 		hdd_err("ND Offload flag attribute not present");
15464 		return -EINVAL;
15465 	}
15466 
15467 	hdd_ctx->ns_offload_enable =
15468 		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
15469 
15470 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
15471 	if (!vdev)
15472 		return -EINVAL;
15473 
15474 	/* update ns offload in case it is already enabled/disabled */
15475 	if (hdd_ctx->ns_offload_enable)
15476 		hdd_enable_ns_offload(adapter, vdev,
15477 				      pmo_ns_offload_dynamic_update);
15478 	else
15479 		hdd_disable_ns_offload(adapter, vdev,
15480 				       pmo_ns_offload_dynamic_update);
15481 
15482 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
15483 	return 0;
15484 }
15485 
15486 /**
15487  * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
15488  * @wiphy:   pointer to wireless wiphy structure.
15489  * @wdev:    pointer to wireless_dev structure.
15490  * @data:    Pointer to the data to be passed via vendor interface
15491  * @data_len:Length of the data to be passed
15492  *
15493  * Return:   Return the Success or Failure code.
15494  */
15495 static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
15496 					struct wireless_dev *wdev,
15497 					const void *data, int data_len)
15498 {
15499 	int errno;
15500 	struct osif_vdev_sync *vdev_sync;
15501 
15502 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
15503 	if (errno)
15504 		return errno;
15505 
15506 	errno = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
15507 
15508 	osif_vdev_sync_op_stop(vdev_sync);
15509 
15510 	return errno;
15511 }
15512 #endif /* WLAN_NS_OFFLOAD */
15513 
15514 /**
15515  * struct weighed_pcl: Preferred channel info
15516  * @freq: Channel frequency
15517  * @weight: Weightage of the channel
15518  * @flag: Validity of the channel in p2p negotiation
15519  */
15520 struct weighed_pcl {
15521 		u32 freq;
15522 		u32 weight;
15523 		u32 flag;
15524 };
15525 
15526 const struct nla_policy get_preferred_freq_list_policy[
15527 		QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
15528 	[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
15529 		.type = NLA_U32},
15530 };
15531 
15532 static uint32_t wlan_hdd_populate_weigh_pcl(
15533 				struct wlan_objmgr_psoc *psoc,
15534 				struct policy_mgr_pcl_chan_weights *
15535 				chan_weights,
15536 				struct weighed_pcl *w_pcl,
15537 				enum policy_mgr_con_mode intf_mode)
15538 {
15539 	u32 i, j, valid_weight;
15540 	u32 chan_idx = 0;
15541 	u32 pcl_len = chan_weights->pcl_len;
15542 	u32 conn_count = policy_mgr_get_connection_count(psoc);
15543 
15544 	/* convert channel number to frequency */
15545 	for (i = 0; i < chan_weights->pcl_len; i++) {
15546 		w_pcl[i].freq = chan_weights->pcl_list[i];
15547 		w_pcl[i].weight = chan_weights->weight_list[i];
15548 
15549 		if (policy_mgr_is_beaconing_mode(intf_mode))
15550 			w_pcl[i].flag = PCL_CHANNEL_SUPPORT_GO;
15551 		else
15552 			w_pcl[i].flag = PCL_CHANNEL_SUPPORT_CLI;
15553 	}
15554 	chan_idx = pcl_len;
15555 	if (!conn_count || policy_mgr_is_hw_dbs_capable(psoc) ||
15556 	    policy_mgr_is_interband_mcc_supported(psoc)) {
15557 		if (pcl_len && chan_weights->weight_list[pcl_len - 1] >
15558 		    PCL_GROUPS_WEIGHT_DIFFERENCE)
15559 		/*
15560 		 * Set non-pcl channels weight 20 point less than the
15561 		 * last PCL entry
15562 		 */
15563 			valid_weight = chan_weights->weight_list[pcl_len - 1] -
15564 					PCL_GROUPS_WEIGHT_DIFFERENCE;
15565 		else
15566 			valid_weight = 1;
15567 
15568 		/* Include rest of the valid channels */
15569 		for (i = 0; i < chan_weights->saved_num_chan; i++) {
15570 			for (j = 0; j < chan_weights->pcl_len; j++) {
15571 				if (chan_weights->saved_chan_list[i] ==
15572 					chan_weights->pcl_list[j])
15573 					break;
15574 			}
15575 			if (j == chan_weights->pcl_len) {
15576 				w_pcl[chan_idx].freq =
15577 					chan_weights->saved_chan_list[i];
15578 
15579 				if (!chan_weights->weighed_valid_list[i]) {
15580 					w_pcl[chan_idx].flag =
15581 						PCL_CHANNEL_EXCLUDE_IN_GO_NEG;
15582 					w_pcl[chan_idx].weight = 0;
15583 				} else {
15584 					if (policy_mgr_is_beaconing_mode(
15585 								intf_mode))
15586 						w_pcl[chan_idx].flag =
15587 						      PCL_CHANNEL_SUPPORT_GO;
15588 					else
15589 						w_pcl[chan_idx].flag =
15590 						      PCL_CHANNEL_SUPPORT_CLI;
15591 					w_pcl[chan_idx].weight = valid_weight;
15592 				}
15593 				chan_idx++;
15594 			}
15595 		}
15596 	}
15597 	return chan_idx;
15598 }
15599 
15600 /** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
15601  * @wiphy: Pointer to wireless phy
15602  * @wdev: Pointer to wireless device
15603  * @data: Pointer to data
15604  * @data_len: Data length
15605  *
15606  * This function return the preferred frequency list generated by the policy
15607  * manager.
15608  *
15609  * Return: success or failure code
15610  */
15611 static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
15612 						 struct wireless_dev
15613 						 *wdev, const void *data,
15614 						 int data_len)
15615 {
15616 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15617 	int i, ret = 0;
15618 	QDF_STATUS status;
15619 	uint32_t pcl_len = 0;
15620 	uint32_t pcl_len_legacy = 0;
15621 	uint32_t freq_list[NUM_CHANNELS];
15622 	uint32_t freq_list_legacy[NUM_CHANNELS];
15623 	enum policy_mgr_con_mode intf_mode;
15624 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
15625 	struct sk_buff *reply_skb;
15626 	struct weighed_pcl *w_pcl;
15627 	struct nlattr *nla_attr, *channel;
15628 	struct policy_mgr_pcl_chan_weights *chan_weights;
15629 	struct net_device *ndev = wdev->netdev;
15630 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
15631 
15632 	hdd_enter_dev(wdev->netdev);
15633 
15634 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15635 		hdd_err("Command not allowed in FTM mode");
15636 		return -EPERM;
15637 	}
15638 
15639 	ret = wlan_hdd_validate_context(hdd_ctx);
15640 	if (ret)
15641 		return -EINVAL;
15642 
15643 	if (wlan_cfg80211_nla_parse(tb,
15644 			       QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
15645 			       data, data_len,
15646 			       get_preferred_freq_list_policy)) {
15647 		hdd_err("Invalid ATTR");
15648 		return -EINVAL;
15649 	}
15650 
15651 	if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
15652 		hdd_err("attr interface type failed");
15653 		return -EINVAL;
15654 	}
15655 
15656 	intf_mode = nla_get_u32(tb
15657 		    [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
15658 
15659 	if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
15660 		hdd_err("Invalid interface type");
15661 		return -EINVAL;
15662 	}
15663 
15664 	hdd_debug("Userspace requested pref freq list");
15665 
15666 	chan_weights =
15667 		qdf_mem_malloc(sizeof(struct policy_mgr_pcl_chan_weights));
15668 	if (!chan_weights)
15669 		return -ENOMEM;
15670 
15671 	status = policy_mgr_get_pcl(
15672 			hdd_ctx->psoc, intf_mode, chan_weights->pcl_list,
15673 			&chan_weights->pcl_len, chan_weights->weight_list,
15674 			QDF_ARRAY_SIZE(chan_weights->weight_list),
15675 			adapter->deflink->vdev_id);
15676 	if (status != QDF_STATUS_SUCCESS) {
15677 		hdd_err("Get pcl failed");
15678 		qdf_mem_free(chan_weights);
15679 		return -EINVAL;
15680 	}
15681 	/*
15682 	 * save the pcl in freq_list_legacy to be sent up with
15683 	 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST.
15684 	 * freq_list will carry the extended pcl in
15685 	 * QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL.
15686 	 */
15687 	pcl_len_legacy = chan_weights->pcl_len;
15688 	for (i = 0; i < pcl_len_legacy; i++)
15689 		freq_list_legacy[i] = chan_weights->pcl_list[i];
15690 	chan_weights->saved_num_chan = NUM_CHANNELS;
15691 	ucfg_mlme_get_valid_channels(hdd_ctx->psoc,
15692 				     chan_weights->saved_chan_list,
15693 				     &chan_weights->saved_num_chan);
15694 	policy_mgr_get_valid_chan_weights(hdd_ctx->psoc, chan_weights,
15695 					  intf_mode,
15696 					  adapter->deflink->vdev);
15697 	w_pcl = qdf_mem_malloc(sizeof(struct weighed_pcl) * NUM_CHANNELS);
15698 	if (!w_pcl) {
15699 		qdf_mem_free(chan_weights);
15700 		return -ENOMEM;
15701 	}
15702 	pcl_len = wlan_hdd_populate_weigh_pcl(hdd_ctx->psoc, chan_weights,
15703 					      w_pcl, intf_mode);
15704 	qdf_mem_free(chan_weights);
15705 
15706 	for (i = 0; i < pcl_len; i++)
15707 		freq_list[i] = w_pcl[i].freq;
15708 
15709 	/* send the freq_list back to supplicant */
15710 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(
15711 			wiphy,
15712 			(sizeof(u32) + NLA_HDRLEN) +
15713 			(sizeof(u32) * pcl_len_legacy + NLA_HDRLEN) +
15714 			NLA_HDRLEN +
15715 			(NLA_HDRLEN * 4 + sizeof(u32) * 3) * pcl_len +
15716 			NLMSG_HDRLEN);
15717 
15718 	if (!reply_skb) {
15719 		hdd_err("Allocate reply_skb failed");
15720 		qdf_mem_free(w_pcl);
15721 		return -EINVAL;
15722 	}
15723 
15724 	if (nla_put_u32(reply_skb,
15725 		QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
15726 			intf_mode) ||
15727 	    nla_put(reply_skb,
15728 		    QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
15729 		    sizeof(uint32_t) * pcl_len_legacy,
15730 		    freq_list_legacy)) {
15731 		hdd_err("nla put fail");
15732 		wlan_cfg80211_vendor_free_skb(reply_skb);
15733 		qdf_mem_free(w_pcl);
15734 		return -EINVAL;
15735 	}
15736 
15737 	i = QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL;
15738 	nla_attr = nla_nest_start(reply_skb, i);
15739 
15740 	if (!nla_attr) {
15741 		hdd_err("nla nest start fail");
15742 		wlan_cfg80211_vendor_free_skb(reply_skb);
15743 		qdf_mem_free(w_pcl);
15744 		return -EINVAL;
15745 	}
15746 
15747 	for (i = 0; i < pcl_len; i++) {
15748 		channel = nla_nest_start(reply_skb, i);
15749 		if (!channel) {
15750 			hdd_err("updating pcl list failed");
15751 			wlan_cfg80211_vendor_free_skb(reply_skb);
15752 			qdf_mem_free(w_pcl);
15753 			return -EINVAL;
15754 		}
15755 		if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FREQ,
15756 				w_pcl[i].freq) ||
15757 		    nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
15758 				w_pcl[i].weight) ||
15759 		    nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_PCL_FLAG,
15760 				w_pcl[i].flag)) {
15761 			hdd_err("nla put fail");
15762 			wlan_cfg80211_vendor_free_skb(reply_skb);
15763 			qdf_mem_free(w_pcl);
15764 			return -EINVAL;
15765 		}
15766 		nla_nest_end(reply_skb, channel);
15767 	}
15768 	nla_nest_end(reply_skb, nla_attr);
15769 	qdf_mem_free(w_pcl);
15770 
15771 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
15772 }
15773 
15774 /** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
15775  * @wiphy: Pointer to wireless phy
15776  * @wdev: Pointer to wireless device
15777  * @data: Pointer to data
15778  * @data_len: Data length
15779  *
15780  * This function return the preferred frequency list generated by the policy
15781  * manager.
15782  *
15783  * Return: success or failure code
15784  */
15785 static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
15786 						 struct wireless_dev
15787 						 *wdev, const void *data,
15788 						 int data_len)
15789 {
15790 	struct osif_psoc_sync *psoc_sync;
15791 	int errno;
15792 
15793 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
15794 	if (errno)
15795 		return errno;
15796 
15797 	errno = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
15798 							    data, data_len);
15799 
15800 	osif_psoc_sync_op_stop(psoc_sync);
15801 
15802 	return errno;
15803 }
15804 
15805 const struct nla_policy set_probable_oper_channel_policy[
15806 		QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
15807 	[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
15808 		.type = NLA_U32},
15809 	[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
15810 		.type = NLA_U32},
15811 };
15812 
15813 /**
15814  * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
15815  * @wiphy: Pointer to wireless phy
15816  * @wdev: Pointer to wireless device
15817  * @data: Pointer to data
15818  * @data_len: Data length
15819  *
15820  * Return: 0 on success, negative errno on failure
15821  */
15822 static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
15823 						struct wireless_dev *wdev,
15824 						const void *data,
15825 						int data_len)
15826 {
15827 	struct net_device *ndev = wdev->netdev;
15828 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
15829 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15830 	int ret = 0;
15831 	enum policy_mgr_con_mode intf_mode;
15832 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
15833 	uint32_t ch_freq, conc_ext_flags;
15834 
15835 	hdd_enter_dev(ndev);
15836 
15837 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15838 		hdd_err("Command not allowed in FTM mode");
15839 		return -EPERM;
15840 	}
15841 
15842 	ret = wlan_hdd_validate_context(hdd_ctx);
15843 	if (ret)
15844 		return ret;
15845 
15846 	if (wlan_cfg80211_nla_parse(tb,
15847 				 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
15848 				 data, data_len,
15849 				 set_probable_oper_channel_policy)) {
15850 		hdd_err("Invalid ATTR");
15851 		return -EINVAL;
15852 	}
15853 
15854 	if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
15855 		hdd_err("attr interface type failed");
15856 		return -EINVAL;
15857 	}
15858 
15859 	intf_mode = nla_get_u32(tb
15860 		    [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
15861 
15862 	if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
15863 		hdd_err("Invalid interface type");
15864 		return -EINVAL;
15865 	}
15866 
15867 	if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
15868 		hdd_err("attr probable freq failed");
15869 		return -EINVAL;
15870 	}
15871 
15872 	ch_freq = nla_get_u32(tb[
15873 			      QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]);
15874 	conc_ext_flags = policy_mgr_get_conc_ext_flags(adapter->deflink->vdev,
15875 						       false);
15876 
15877 	/* check pcl table */
15878 	if (!policy_mgr_allow_concurrency(hdd_ctx->psoc, intf_mode,
15879 					  ch_freq, HW_MODE_20_MHZ,
15880 					  conc_ext_flags,
15881 					  adapter->deflink->vdev_id)) {
15882 		hdd_err("Set channel hint failed due to concurrency check");
15883 		return -EINVAL;
15884 	}
15885 
15886 	if (QDF_P2P_GO_MODE != adapter->device_mode)
15887 		wlan_hdd_cleanup_remain_on_channel_ctx(adapter->deflink);
15888 
15889 	if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, ch_freq,
15890 				POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
15891 		hdd_err("Failed to change hw mode");
15892 		return -EINVAL;
15893 	}
15894 
15895 	return 0;
15896 }
15897 
15898 /**
15899  * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
15900  * @wiphy: Pointer to wireless phy
15901  * @wdev: Pointer to wireless device
15902  * @data: Pointer to data
15903  * @data_len: Data length
15904  *
15905  * Return: 0 on success, negative errno on failure
15906  */
15907 static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
15908 						struct wireless_dev *wdev,
15909 						const void *data,
15910 						int data_len)
15911 {
15912 	int errno;
15913 	struct osif_vdev_sync *vdev_sync;
15914 
15915 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
15916 	if (errno)
15917 		return errno;
15918 
15919 	errno = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
15920 							      data, data_len);
15921 
15922 	osif_vdev_sync_op_stop(vdev_sync);
15923 
15924 	return errno;
15925 }
15926 
15927 static const struct
15928 nla_policy
15929 wlan_hdd_get_link_properties_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
15930 	[QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
15931 		.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
15932 };
15933 
15934 /**
15935  * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
15936  * @wiphy: WIPHY structure pointer
15937  * @wdev: Wireless device structure pointer
15938  * @data: Pointer to the data received
15939  * @data_len: Length of the data received
15940  *
15941  * This function is used to get link properties like nss, rate flags and
15942  * operating frequency for the active connection with the given peer.
15943  *
15944  * Return: 0 on success and errno on failure
15945  */
15946 static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
15947 						   struct wireless_dev *wdev,
15948 						   const void *data,
15949 						   int data_len)
15950 {
15951 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15952 	struct net_device *dev = wdev->netdev;
15953 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15954 	struct hdd_station_ctx *hdd_sta_ctx;
15955 	struct hdd_ap_ctx *ap_ctx;
15956 	struct hdd_station_info *sta_info;
15957 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
15958 	uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
15959 	struct sk_buff *reply_skb;
15960 	uint32_t rate_flags = 0;
15961 	uint8_t nss;
15962 	uint8_t final_rate_flags = 0;
15963 	uint32_t freq;
15964 
15965 	hdd_enter_dev(dev);
15966 
15967 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
15968 		hdd_err("Command not allowed in FTM mode");
15969 		return -EPERM;
15970 	}
15971 
15972 	if (0 != wlan_hdd_validate_context(hdd_ctx))
15973 		return -EINVAL;
15974 
15975 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
15976 				    data_len,
15977 				    wlan_hdd_get_link_properties_policy)) {
15978 		hdd_err("Invalid attribute");
15979 		return -EINVAL;
15980 	}
15981 
15982 	if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
15983 		hdd_err("Attribute peerMac not provided for mode=%d",
15984 		       adapter->device_mode);
15985 		return -EINVAL;
15986 	}
15987 
15988 	if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
15989 		hdd_err("Attribute peerMac is invalid for mode=%d",
15990 			adapter->device_mode);
15991 		return -EINVAL;
15992 	}
15993 
15994 	qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
15995 		     QDF_MAC_ADDR_SIZE);
15996 	hdd_debug("peerMac="QDF_MAC_ADDR_FMT" for device_mode:%d",
15997 		  QDF_MAC_ADDR_REF(peer_mac), adapter->device_mode);
15998 
15999 	if (adapter->device_mode == QDF_STA_MODE ||
16000 	    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
16001 		hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
16002 		if (!hdd_cm_is_vdev_associated(adapter->deflink) ||
16003 		    qdf_mem_cmp(hdd_sta_ctx->conn_info.bssid.bytes,
16004 			peer_mac, QDF_MAC_ADDR_SIZE)) {
16005 			hdd_err("Not Associated to mac "QDF_MAC_ADDR_FMT,
16006 			       QDF_MAC_ADDR_REF(peer_mac));
16007 			return -EINVAL;
16008 		}
16009 
16010 		nss  = hdd_sta_ctx->conn_info.nss;
16011 		freq = hdd_sta_ctx->conn_info.chan_freq;
16012 		rate_flags = hdd_sta_ctx->conn_info.rate_flags;
16013 	} else if (adapter->device_mode == QDF_P2P_GO_MODE ||
16014 		   adapter->device_mode == QDF_SAP_MODE) {
16015 
16016 		if (QDF_IS_ADDR_BROADCAST(peer_mac)) {
16017 			hdd_err("Ignore bcast/self sta");
16018 			return -EINVAL;
16019 		}
16020 
16021 		sta_info = hdd_get_sta_info_by_mac(
16022 					&adapter->sta_info_list, peer_mac,
16023 					STA_INFO_CFG80211_GET_LINK_PROPERTIES);
16024 
16025 		if (!sta_info) {
16026 			hdd_err("No active peer with mac = " QDF_MAC_ADDR_FMT,
16027 				QDF_MAC_ADDR_REF(peer_mac));
16028 			return -EINVAL;
16029 		}
16030 
16031 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
16032 		nss = sta_info->nss;
16033 		freq = ap_ctx->operating_chan_freq;
16034 		rate_flags = sta_info->rate_flags;
16035 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
16036 				     STA_INFO_CFG80211_GET_LINK_PROPERTIES);
16037 	} else {
16038 		hdd_err("Not Associated! with mac "QDF_MAC_ADDR_FMT,
16039 		       QDF_MAC_ADDR_REF(peer_mac));
16040 		return -EINVAL;
16041 	}
16042 
16043 	if (!(rate_flags & TX_RATE_LEGACY)) {
16044 		if (rate_flags & TX_RATE_VHT80) {
16045 			final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
16046 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
16047 			final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
16048 #endif
16049 		} else if (rate_flags & TX_RATE_VHT40) {
16050 			final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
16051 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
16052 			final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
16053 #endif
16054 		} else if (rate_flags & TX_RATE_VHT20) {
16055 			final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
16056 		} else if (rate_flags &
16057 				(TX_RATE_HT20 | TX_RATE_HT40)) {
16058 			final_rate_flags |= RATE_INFO_FLAGS_MCS;
16059 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
16060 			if (rate_flags & TX_RATE_HT40)
16061 				final_rate_flags |=
16062 					RATE_INFO_FLAGS_40_MHZ_WIDTH;
16063 #endif
16064 		}
16065 
16066 		if (rate_flags & TX_RATE_SGI) {
16067 			if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
16068 				final_rate_flags |= RATE_INFO_FLAGS_MCS;
16069 			final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
16070 		}
16071 	}
16072 
16073 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
16074 							     sizeof(u8) +
16075 							     sizeof(u8) +
16076 							     sizeof(u32) +
16077 							     NLMSG_HDRLEN);
16078 	if (!reply_skb) {
16079 		hdd_err("getLinkProperties: skb alloc failed");
16080 		return -EINVAL;
16081 	}
16082 
16083 	if (nla_put_u8(reply_skb,
16084 		QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
16085 		nss) ||
16086 	    nla_put_u8(reply_skb,
16087 		QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
16088 		final_rate_flags) ||
16089 	    nla_put_u32(reply_skb,
16090 		QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
16091 		freq)) {
16092 		hdd_err("nla_put failed");
16093 		wlan_cfg80211_vendor_free_skb(reply_skb);
16094 		return -EINVAL;
16095 	}
16096 
16097 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
16098 }
16099 
16100 /**
16101  * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
16102  * properties.
16103  * @wiphy: WIPHY structure pointer
16104  * @wdev: Wireless device structure pointer
16105  * @data: Pointer to the data received
16106  * @data_len: Length of the data received
16107  *
16108  * This function is used to get link properties like nss, rate flags and
16109  * operating frequency for the active connection with the given peer.
16110  *
16111  * Return: 0 on success and errno on failure
16112  */
16113 static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
16114 						 struct wireless_dev *wdev,
16115 						 const void *data,
16116 						 int data_len)
16117 {
16118 	int errno;
16119 	struct osif_vdev_sync *vdev_sync;
16120 
16121 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16122 	if (errno)
16123 		return errno;
16124 
16125 	errno = __wlan_hdd_cfg80211_get_link_properties(wiphy, wdev,
16126 							data, data_len);
16127 
16128 	osif_vdev_sync_op_stop(vdev_sync);
16129 
16130 	return errno;
16131 }
16132 
16133 const struct nla_policy
16134 wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
16135 	[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8},
16136 	[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY] = {.type = NLA_U32},
16137 	[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
16138 							.type = NLA_BINARY},
16139 };
16140 
16141 const struct nla_policy
16142 wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
16143 	[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8},
16144 	[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8},
16145 	[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT] = {.type = NLA_U32},
16146 };
16147 
16148 /**
16149  * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
16150  * @wiphy: Pointer to wireless phy
16151  * @wdev: Pointer to wireless device
16152  * @data: Pointer to data
16153  * @data_len: Length of @data
16154  *
16155  * This function parses the incoming NL vendor command data attributes and
16156  * updates the SAP context about channel_hint and DFS mode.
16157  * If channel_hint is set, SAP will choose that channel
16158  * as operating channel.
16159  *
16160  * If DFS mode is enabled, driver will include DFS channels
16161  * in ACS else driver will skip DFS channels.
16162  *
16163  * Return: 0 on success, negative errno on failure
16164  */
16165 static int
16166 __wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
16167 		struct wireless_dev *wdev,
16168 		const void *data, int data_len)
16169 {
16170 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16171 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
16172 	int ret;
16173 	struct acs_dfs_policy *acs_policy;
16174 	int mode = DFS_MODE_NONE;
16175 	uint32_t freq_hint = 0;
16176 
16177 	hdd_enter_dev(wdev->netdev);
16178 
16179 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16180 		hdd_err("Command not allowed in FTM mode");
16181 		return -EINVAL;
16182 	}
16183 
16184 	ret = wlan_hdd_validate_context(hdd_ctx);
16185 	if (0 != ret)
16186 		return ret;
16187 
16188 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
16189 				    data, data_len,
16190 				    wlan_hdd_set_acs_dfs_config_policy)) {
16191 		hdd_err("invalid attr");
16192 		return -EINVAL;
16193 	}
16194 
16195 	acs_policy = &hdd_ctx->acs_policy;
16196 	/*
16197 	 * SCM sends this attribute to restrict SAP from choosing
16198 	 * DFS channels from ACS.
16199 	 */
16200 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
16201 		mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
16202 
16203 	if (!IS_DFS_MODE_VALID(mode)) {
16204 		hdd_err("attr acs dfs mode is not valid");
16205 		return -EINVAL;
16206 	}
16207 	acs_policy->acs_dfs_mode = mode;
16208 
16209 	/*
16210 	 * SCM sends this attribute to provide an active channel,
16211 	 * to skip redundant ACS between drivers, and save driver start up time
16212 	 */
16213 	if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]) {
16214 		freq_hint = nla_get_u32(
16215 				tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT]);
16216 	} else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]) {
16217 		uint32_t channel_hint = nla_get_u8(
16218 				tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
16219 
16220 		freq_hint = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
16221 							 channel_hint);
16222 	}
16223 
16224 	if (freq_hint && !WLAN_REG_IS_24GHZ_CH_FREQ(freq_hint) &&
16225 	    !WLAN_REG_IS_5GHZ_CH_FREQ(freq_hint) &&
16226 	    !WLAN_REG_IS_6GHZ_CHAN_FREQ(freq_hint)) {
16227 		hdd_err("acs channel frequency is not valid");
16228 		return -EINVAL;
16229 	}
16230 
16231 	acs_policy->acs_chan_freq = freq_hint;
16232 
16233 	return 0;
16234 }
16235 
16236 /**
16237  * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
16238  * @wiphy:    wiphy structure pointer
16239  * @wdev:     Wireless device structure pointer
16240  * @data:     Pointer to the data received
16241  * @data_len: Length of @data
16242  *
16243  * This function parses the incoming NL vendor command data attributes and
16244  * updates the SAP context about channel_hint and DFS mode.
16245  *
16246  * Return: 0 on success; errno on failure
16247  */
16248 static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
16249 		struct wireless_dev *wdev,
16250 		const void *data, int data_len)
16251 {
16252 	struct osif_psoc_sync *psoc_sync;
16253 	int errno;
16254 
16255 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
16256 	if (errno)
16257 		return errno;
16258 
16259 	errno = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
16260 
16261 	osif_psoc_sync_op_stop(psoc_sync);
16262 
16263 	return errno;
16264 }
16265 
16266 /**
16267  * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
16268  * @mode : cfg80211 dfs mode
16269  *
16270  * Return: return csr sta roam dfs mode else return NONE
16271  */
16272 static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
16273 		enum dfs_mode mode)
16274 {
16275 	switch (mode) {
16276 	case DFS_MODE_ENABLE:
16277 		return STA_ROAM_POLICY_DFS_ENABLED;
16278 	case DFS_MODE_DISABLE:
16279 		return STA_ROAM_POLICY_DFS_DISABLED;
16280 	case DFS_MODE_DEPRIORITIZE:
16281 		return STA_ROAM_POLICY_DFS_DEPRIORITIZE;
16282 	default:
16283 		hdd_err("STA Roam policy dfs mode is NONE");
16284 		return  STA_ROAM_POLICY_NONE;
16285 	}
16286 }
16287 
16288 uint8_t
16289 hdd_get_sap_operating_band_by_link_info(struct wlan_hdd_link_info *link_info)
16290 {
16291 	uint32_t operating_chan_freq;
16292 	uint8_t sap_operating_band = 0;
16293 	struct hdd_ap_ctx *ap_ctx;
16294 	enum QDF_OPMODE opmode = link_info->adapter->device_mode;
16295 
16296 	if (opmode != QDF_SAP_MODE && opmode != QDF_P2P_GO_MODE)
16297 		return BAND_UNKNOWN;
16298 
16299 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
16300 	operating_chan_freq = ap_ctx->operating_chan_freq;
16301 
16302 	if (WLAN_REG_IS_24GHZ_CH_FREQ(operating_chan_freq))
16303 		sap_operating_band = BAND_2G;
16304 	else if (WLAN_REG_IS_5GHZ_CH_FREQ(operating_chan_freq) ||
16305 		 WLAN_REG_IS_6GHZ_CHAN_FREQ(operating_chan_freq))
16306 		sap_operating_band = BAND_5G;
16307 	else
16308 		sap_operating_band = BAND_UNKNOWN;
16309 
16310 	return sap_operating_band;
16311 }
16312 
16313 /*
16314  * hdd_get_sap_operating_band:  Get current operating channel
16315  * for sap.
16316  * @hdd_ctx: hdd context
16317  *
16318  * Return : Corresponding band for SAP operating channel
16319  */
16320 uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
16321 {
16322 	struct hdd_adapter *adapter, *next_adapter = NULL;
16323 	uint8_t operating_band = 0;
16324 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_SAP_OPERATING_BAND;
16325 	struct wlan_hdd_link_info *link_info;
16326 
16327 	hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter,
16328 					   dbgid) {
16329 		if (adapter->device_mode != QDF_SAP_MODE) {
16330 			hdd_adapter_dev_put_debug(adapter, dbgid);
16331 			continue;
16332 		}
16333 
16334 		link_info = adapter->deflink;
16335 		operating_band =
16336 			hdd_get_sap_operating_band_by_link_info(link_info);
16337 
16338 		hdd_adapter_dev_put_debug(adapter, dbgid);
16339 	}
16340 
16341 	return operating_band;
16342 }
16343 
16344 static inline QDF_STATUS
16345 wlan_hdd_config_dp_direct_link_profile(struct hdd_adapter *adapter,
16346 				       enum host_concurrent_ap_policy ap_policy)
16347 {
16348 	struct wlan_objmgr_vdev *vdev = adapter->deflink->vdev;
16349 	enum host_concurrent_ap_policy prev_ap_policy;
16350 
16351 	prev_ap_policy = ucfg_mlme_get_ap_policy(vdev);
16352 
16353 	hdd_debug("Current AP policy %d prev AP policy %d", ap_policy,
16354 		  prev_ap_policy);
16355 
16356 	switch (prev_ap_policy) {
16357 	case HOST_CONCURRENT_AP_POLICY_UNSPECIFIED:
16358 		switch (ap_policy) {
16359 		case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
16360 			return ucfg_dp_config_direct_link(adapter->dev, true,
16361 							  false);
16362 		case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
16363 			return ucfg_dp_config_direct_link(adapter->dev, true,
16364 							  true);
16365 		default:
16366 			break;
16367 		}
16368 		break;
16369 	case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
16370 		switch (ap_policy) {
16371 		case HOST_CONCURRENT_AP_POLICY_UNSPECIFIED:
16372 		case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
16373 			return ucfg_dp_config_direct_link(adapter->dev, true,
16374 							  false);
16375 		default:
16376 			break;
16377 		}
16378 		break;
16379 	case HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING:
16380 		switch (ap_policy) {
16381 		case HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO:
16382 			return ucfg_dp_config_direct_link(adapter->dev, true,
16383 							  true);
16384 		default:
16385 			break;
16386 		}
16387 		break;
16388 	default:
16389 		break;
16390 	}
16391 
16392 	return QDF_STATUS_SUCCESS;
16393 }
16394 
16395 const struct nla_policy
16396 wlan_hdd_set_sta_roam_config_policy[
16397 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
16398 	[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
16399 	[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
16400 };
16401 
16402 /**
16403  * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
16404  * for station connection or roaming.
16405  * @wiphy: Pointer to wireless phy
16406  * @wdev: Pointer to wireless device
16407  * @data: Pointer to data
16408  * @data_len: Length of @data
16409  *
16410  * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
16411  * channels needs to be skipped in scanning or not.
16412  * If dfs_mode is disabled, driver will not scan DFS channels.
16413  * If skip_unsafe_channels is set, driver will skip unsafe channels
16414  * in Scanning.
16415  *
16416  * Return: 0 on success, negative errno on failure
16417  */
16418 static int
16419 __wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
16420 				    struct wireless_dev *wdev,
16421 				    const void *data, int data_len)
16422 {
16423 	struct net_device *dev = wdev->netdev;
16424 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16425 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16426 	struct nlattr *tb[
16427 		QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
16428 	int ret;
16429 	enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
16430 	enum dfs_mode mode = DFS_MODE_NONE;
16431 	bool skip_unsafe_channels = false;
16432 	QDF_STATUS status;
16433 	uint8_t sap_operating_band;
16434 	mac_handle_t mac_handle;
16435 
16436 	hdd_enter_dev(dev);
16437 
16438 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16439 		hdd_err("Command not allowed in FTM mode");
16440 		return -EINVAL;
16441 	}
16442 
16443 	ret = wlan_hdd_validate_context(hdd_ctx);
16444 	if (0 != ret)
16445 		return ret;
16446 	if (wlan_cfg80211_nla_parse(tb,
16447 			       QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
16448 			       data, data_len,
16449 			       wlan_hdd_set_sta_roam_config_policy)) {
16450 		hdd_err("invalid attr");
16451 		return -EINVAL;
16452 	}
16453 	if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
16454 		mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
16455 	if (!IS_DFS_MODE_VALID(mode)) {
16456 		hdd_err("attr sta roam dfs mode policy is not valid");
16457 		return -EINVAL;
16458 	}
16459 
16460 	sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
16461 
16462 	if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
16463 		skip_unsafe_channels = nla_get_u8(
16464 			tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
16465 	sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
16466 	mac_handle = hdd_ctx->mac_handle;
16467 	status = sme_update_sta_roam_policy(mac_handle, sta_roam_dfs_mode,
16468 					    skip_unsafe_channels,
16469 					    adapter->deflink->vdev_id,
16470 					    sap_operating_band);
16471 
16472 	if (!QDF_IS_STATUS_SUCCESS(status)) {
16473 		hdd_err("sme_update_sta_roam_policy (err=%d)", status);
16474 		return -EINVAL;
16475 	}
16476 	return 0;
16477 }
16478 
16479 /**
16480  * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
16481  * connection and roaming for station.
16482  * @wiphy:    wiphy structure pointer
16483  * @wdev:     Wireless device structure pointer
16484  * @data:     Pointer to the data received
16485  * @data_len: Length of @data
16486  *
16487  * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
16488  * channels needs to be skipped in scanning or not.
16489  * If dfs_mode is disabled, driver will not scan DFS channels.
16490  * If skip_unsafe_channels is set, driver will skip unsafe channels
16491  * in Scanning.
16492  * Return: 0 on success; errno on failure
16493  */
16494 static int
16495 wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
16496 				  struct wireless_dev *wdev, const void *data,
16497 				  int data_len)
16498 {
16499 	int errno;
16500 	struct osif_vdev_sync *vdev_sync;
16501 
16502 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16503 	if (errno)
16504 		return errno;
16505 
16506 	errno = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev,
16507 						    data, data_len);
16508 
16509 	osif_vdev_sync_op_stop(vdev_sync);
16510 
16511 	return errno;
16512 }
16513 
16514 const struct nla_policy
16515 wlan_hdd_set_concurrent_session_policy[
16516 QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX + 1] = {
16517 	[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG] = {.type = NLA_U8 },
16518 	[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG] = {.type = NLA_U8 },
16519 };
16520 
16521 /**
16522  * __wlan_hdd_cfg80211_dual_sta_policy() - Wrapper to configure the concurrent
16523  * session policies
16524  * @hdd_ctx: Pointer to HDD context
16525  * @tb: parsed attribute array
16526  *
16527  * Configure the concurrent session policies when multiple STA ifaces are
16528  * (getting) active.
16529  * Return: 0 on success; errno on failure
16530  */
16531 static int __wlan_hdd_cfg80211_dual_sta_policy(struct hdd_context *hdd_ctx,
16532 					       struct nlattr **tb)
16533 {
16534 	QDF_STATUS status;
16535 	uint8_t dual_sta_config =
16536 		QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED;
16537 
16538 	dual_sta_config = nla_get_u8(
16539 			tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG]);
16540 	hdd_debug("Concurrent STA policy : %d", dual_sta_config);
16541 
16542 	if (dual_sta_config > QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED)
16543 		return -EINVAL;
16544 
16545 	status = ucfg_mlme_set_dual_sta_policy(hdd_ctx->psoc, dual_sta_config);
16546 	if (QDF_IS_STATUS_ERROR(status)) {
16547 		hdd_err("failed to set MLME dual sta config");
16548 		return -EINVAL;
16549 	}
16550 
16551 	/* After SSR, the dual sta configuration is lost. As SSR is hidden from
16552 	 * userland, this command will not come from userspace after a SSR. To
16553 	 * restore this configuration, save this in hdd context and restore
16554 	 * after re-init.
16555 	 */
16556 	hdd_ctx->dual_sta_policy.dual_sta_policy = dual_sta_config;
16557 
16558 	return 0;
16559 }
16560 
16561 /**
16562  * __wlan_hdd_cfg80211_ap_policy() - Wrapper to configure the concurrent
16563  * session policies
16564  * @adapter: HDD adapter
16565  * @tb: parsed attribute array
16566  *
16567  * Configure the concurrent session policies when multiple STA ifaces are
16568  * (getting) active.
16569  * Return: 0 on success; errno on failure
16570  */
16571 static int __wlan_hdd_cfg80211_ap_policy(struct hdd_adapter *adapter,
16572 					 struct nlattr **tb)
16573 {
16574 	QDF_STATUS status;
16575 	uint8_t vdev_id;
16576 	int ret;
16577 	uint8_t ap_cfg_policy;
16578 	uint32_t profile = 0;
16579 	enum QDF_OPMODE device_mode;
16580 	uint8_t ap_config =
16581 		QCA_WLAN_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING;
16582 
16583 	vdev_id = wlan_vdev_get_id(adapter->deflink->vdev);
16584 	device_mode = hdd_get_device_mode(vdev_id);
16585 	if (device_mode != QDF_SAP_MODE) {
16586 		hdd_err_rl("command not allowed in %d mode, vdev_id: %d",
16587 			   device_mode, vdev_id);
16588 		return -EINVAL;
16589 	}
16590 
16591 	ap_config = nla_get_u8(
16592 		tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG]);
16593 	hdd_debug("AP policy : %d", ap_config);
16594 
16595 	if (ap_config > QCA_WLAN_CONCURRENT_AP_POLICY_XR) {
16596 		hdd_err_rl("Invalid concurrent policy ap config %d", ap_config);
16597 		return -EINVAL;
16598 	}
16599 
16600 	ap_cfg_policy = wlan_mlme_convert_ap_policy_config(ap_config);
16601 	if (ap_cfg_policy == HOST_CONCURRENT_AP_POLICY_XR)
16602 		profile = AP_PROFILE_XR_ENABLE;
16603 	else if (ap_cfg_policy == HOST_CONCURRENT_AP_POLICY_GAMING_AUDIO ||
16604 		 ap_cfg_policy ==
16605 		 HOST_CONCURRENT_AP_POLICY_LOSSLESS_AUDIO_STREAMING)
16606 		profile = AP_PROFILE_XPAN_ENABLE;
16607 	ret = wma_cli_set_command(vdev_id, wmi_vdev_param_set_profile,
16608 				  profile, VDEV_CMD);
16609 	if (ret) {
16610 		hdd_err("Failed to set profile %d", profile);
16611 		return -EINVAL;
16612 	}
16613 	status = wlan_hdd_config_dp_direct_link_profile(adapter, ap_cfg_policy);
16614 	if (QDF_IS_STATUS_ERROR(status)) {
16615 		hdd_err("failed to set DP ap config");
16616 		return -EINVAL;
16617 	}
16618 	status = ucfg_mlme_set_ap_policy(adapter->deflink->vdev, ap_cfg_policy);
16619 	if (QDF_IS_STATUS_ERROR(status)) {
16620 		hdd_err("failed to set MLME ap config");
16621 		return -EINVAL;
16622 	}
16623 
16624 	wlan_mlme_ll_lt_sap_send_oce_flags_fw(adapter->deflink->vdev);
16625 	wlan_vdev_mlme_feat_ext_cap_clear(adapter->deflink->vdev,
16626 					  WLAN_VDEV_FEXT_FILS_DISC_6G_SAP);
16627 	return 0;
16628 }
16629 
16630 /**
16631  * __wlan_hdd_cfg80211_concurrent_session_policy() - Wrapper to configure the
16632  * concurrent session policies
16633  * @wiphy:    wiphy structure pointer
16634  * @wdev:     Wireless device structure pointer
16635  * @data:     Pointer to the data received
16636  * @data_len: Length of @data
16637  *
16638  * Configure the concurrent session policies when low latency SAP or multiple
16639  * STA ifaces are (getting) active.
16640  * Return: 0 on success; errno on failure
16641  */
16642 static int __wlan_hdd_cfg80211_concurrent_session_policy(
16643 						struct wiphy *wiphy,
16644 						struct wireless_dev *wdev,
16645 						const void *data, int data_len)
16646 {
16647 	struct net_device *ndev = wdev->netdev;
16648 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
16649 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX + 1];
16650 
16651 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16652 		hdd_err_rl("Command not allowed in FTM mode");
16653 		return -EPERM;
16654 	}
16655 
16656 	if (hdd_validate_adapter(adapter)) {
16657 		hdd_err_rl("Invalid adapter");
16658 		return -EINVAL;
16659 	}
16660 
16661 	if (wlan_hdd_validate_context(adapter->hdd_ctx)) {
16662 		hdd_err_rl("Invalid hdd context");
16663 		return -EINVAL;
16664 	}
16665 
16666 	if (wlan_cfg80211_nla_parse(
16667 				tb,
16668 				QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX,
16669 				data, data_len,
16670 				wlan_hdd_set_concurrent_session_policy)) {
16671 		hdd_err_rl("nla_parse failed");
16672 		return -EINVAL;
16673 	}
16674 
16675 	if (!tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG] &&
16676 	    !tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG]) {
16677 		hdd_err_rl("concurrent session policy attr not present");
16678 		return -EINVAL;
16679 	}
16680 
16681 	if (tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_STA_CONFIG])
16682 		__wlan_hdd_cfg80211_dual_sta_policy(adapter->hdd_ctx, tb);
16683 
16684 	if (tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_AP_CONFIG])
16685 		__wlan_hdd_cfg80211_ap_policy(adapter, tb);
16686 
16687 	return 0;
16688 }
16689 
16690 /**
16691  * wlan_hdd_cfg80211_concurrent_session_policy() -  Wrapper to configure the
16692  * concurrent session policies
16693  * @wiphy:    wiphy structure pointer
16694  * @wdev:     Wireless device structure pointer
16695  * @data:     Pointer to the data received
16696  * @data_len: Length of @data
16697  *
16698  * Configure the concurrent session policies when multiple STA ifaces are
16699  * (getting) active.
16700  * Return: 0 on success; errno on failure
16701  */
16702 static int wlan_hdd_cfg80211_concurrent_session_policy(
16703 						struct wiphy *wiphy,
16704 						struct wireless_dev *wdev,
16705 						const void *data,
16706 						int data_len)
16707 {
16708 	int errno;
16709 	struct osif_vdev_sync *vdev_sync;
16710 
16711 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16712 	if (errno)
16713 		return errno;
16714 
16715 	errno = __wlan_hdd_cfg80211_concurrent_session_policy(
16716 						wiphy, wdev, data,
16717 						data_len);
16718 
16719 
16720 	osif_vdev_sync_op_stop(vdev_sync);
16721 
16722 	return errno;
16723 }
16724 
16725 #ifdef FEATURE_WLAN_CH_AVOID
16726 /**
16727  * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
16728  * is on unsafe channel.
16729  * @wiphy:    wiphy structure pointer
16730  * @wdev:     Wireless device structure pointer
16731  * @data:     Pointer to the data received
16732  * @data_len: Length of @data
16733  *
16734  * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
16735  * on any of unsafe channels.
16736  * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
16737  * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
16738  *
16739  * Return: 0 on success; errno on failure
16740  */
16741 static int
16742 __wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
16743 		struct wireless_dev *wdev,
16744 		const void *data, int data_len)
16745 {
16746 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16747 	int ret;
16748 	qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
16749 	struct ch_avoid_ind_type *channel_list;
16750 	struct ch_avoid_ind_type avoid_freq_list;
16751 	enum QDF_GLOBAL_MODE curr_mode;
16752 	uint8_t num_args = 0;
16753 
16754 	hdd_enter_dev(wdev->netdev);
16755 
16756 	if (!qdf_ctx)
16757 		return -EINVAL;
16758 
16759 	curr_mode = hdd_get_conparam();
16760 	if (QDF_GLOBAL_FTM_MODE == curr_mode ||
16761 	    QDF_GLOBAL_MONITOR_MODE == curr_mode) {
16762 		hdd_err("Command not allowed in FTM/MONITOR mode");
16763 		return -EINVAL;
16764 	}
16765 
16766 	ret = wlan_hdd_validate_context(hdd_ctx);
16767 	if (0 != ret)
16768 		return ret;
16769 	qdf_mem_zero(&avoid_freq_list, sizeof(struct ch_avoid_ind_type));
16770 
16771 	if (!data && data_len == 0) {
16772 		hdd_debug("Clear avoid frequency list");
16773 		goto process_unsafe_channel;
16774 	}
16775 	if (!data || data_len < (sizeof(channel_list->ch_avoid_range_cnt) +
16776 				 sizeof(struct ch_avoid_freq_type))) {
16777 		hdd_err("Avoid frequency channel list empty");
16778 		return -EINVAL;
16779 	}
16780 	num_args = (data_len - sizeof(channel_list->ch_avoid_range_cnt)) /
16781 		   sizeof(channel_list->avoid_freq_range[0].start_freq);
16782 
16783 
16784 	if (num_args < 2 || num_args > CH_AVOID_MAX_RANGE * 2 ||
16785 	    num_args % 2 != 0) {
16786 		hdd_err("Invalid avoid frequency channel list");
16787 		return -EINVAL;
16788 	}
16789 
16790 	channel_list = (struct ch_avoid_ind_type *)data;
16791 	if (channel_list->ch_avoid_range_cnt == 0 ||
16792 	    channel_list->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE ||
16793 	    2 * channel_list->ch_avoid_range_cnt != num_args) {
16794 		hdd_err("Invalid frequency range count %d",
16795 			channel_list->ch_avoid_range_cnt);
16796 		return -EINVAL;
16797 	}
16798 
16799 	qdf_mem_copy(&avoid_freq_list, channel_list, data_len);
16800 
16801 process_unsafe_channel:
16802 	ucfg_reg_ch_avoid(hdd_ctx->psoc, &avoid_freq_list);
16803 
16804 	return 0;
16805 }
16806 
16807 /**
16808  * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
16809  * is on unsafe channel.
16810  * @wiphy:    wiphy structure pointer
16811  * @wdev:     Wireless device structure pointer
16812  * @data:     Pointer to the data received
16813  * @data_len: Length of @data
16814  *
16815  * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
16816  * on any of unsafe channels.
16817  * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
16818  * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
16819  *
16820  * Return: 0 on success; errno on failure
16821  */
16822 static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
16823 		struct wireless_dev *wdev,
16824 		const void *data, int data_len)
16825 {
16826 	struct osif_psoc_sync *psoc_sync;
16827 	int errno;
16828 
16829 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
16830 	if (errno)
16831 		return errno;
16832 
16833 	errno = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
16834 
16835 	osif_psoc_sync_op_stop(psoc_sync);
16836 
16837 	return errno;
16838 }
16839 
16840 #endif
16841 /**
16842  * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
16843  * SAP is on unsafe channel.
16844  * @wiphy:    wiphy structure pointer
16845  * @wdev:     Wireless device structure pointer
16846  * @data:     Pointer to the data received
16847  * @data_len: Length of @data
16848  *
16849  * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
16850  * driver.
16851  * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
16852  * will initiate restart of sap.
16853  *
16854  * Return: 0 on success; errno on failure
16855  */
16856 static int
16857 __wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
16858 		struct wireless_dev *wdev,
16859 		const void *data, int data_len)
16860 {
16861 	struct net_device *ndev = wdev->netdev;
16862 	struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
16863 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
16864 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
16865 	struct hdd_ap_ctx *ap_ctx;
16866 	int ret;
16867 	uint32_t chan_freq = 0;
16868 	bool chan_freq_present = false;
16869 	QDF_STATUS status;
16870 	struct wlan_hdd_link_info *link_info;
16871 
16872 	hdd_enter();
16873 
16874 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
16875 		hdd_err("Command not allowed in FTM mode");
16876 		return -EINVAL;
16877 	}
16878 
16879 	ret = wlan_hdd_validate_context(hdd_ctx);
16880 	if (0 != ret)
16881 		return -EINVAL;
16882 
16883 	link_info = hostapd_adapter->deflink;
16884 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
16885 				    data, data_len,
16886 				    wlan_hdd_sap_config_policy)) {
16887 		hdd_err("invalid attr");
16888 		return -EINVAL;
16889 	}
16890 
16891 	if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]) {
16892 		chan_freq = nla_get_u32(
16893 				tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY]);
16894 		chan_freq_present = true;
16895 	} else if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
16896 		uint32_t config_channel =
16897 			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
16898 
16899 		chan_freq = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
16900 							 config_channel);
16901 		chan_freq_present = true;
16902 	}
16903 
16904 	if (chan_freq_present) {
16905 		if (!test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
16906 			hdd_err("SAP is not started yet. Restart sap will be invalid");
16907 			return -EINVAL;
16908 		}
16909 
16910 		if (!WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq) &&
16911 		    !WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq) &&
16912 		    !WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq)) {
16913 			hdd_err("Channel frequency %u is invalid to restart SAP",
16914 				chan_freq);
16915 			return -ENOTSUPP;
16916 		}
16917 
16918 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
16919 		ap_ctx->sap_config.chan_freq = chan_freq;
16920 		ap_ctx->sap_config.ch_params.ch_width =
16921 					ap_ctx->sap_config.ch_width_orig;
16922 		ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
16923 
16924 		if (sap_phymode_is_eht(ap_ctx->sap_config.SapHw_mode))
16925 			wlan_reg_set_create_punc_bitmap(
16926 				&ap_ctx->sap_config.ch_params, true);
16927 		wlan_reg_set_channel_params_for_pwrmode(
16928 				hdd_ctx->pdev, chan_freq,
16929 				ap_ctx->sap_config.sec_ch_freq,
16930 				&ap_ctx->sap_config.ch_params,
16931 				REG_CURRENT_PWR_MODE);
16932 
16933 		hdd_restart_sap(link_info);
16934 	}
16935 
16936 	if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
16937 		uint32_t freq_len, i;
16938 		uint32_t *freq;
16939 
16940 		hdd_debug("setting mandatory freq/chan list");
16941 
16942 		freq_len = nla_len(
16943 		    tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
16944 		    sizeof(uint32_t);
16945 
16946 		if (freq_len > NUM_CHANNELS) {
16947 			hdd_err("insufficient space to hold channels");
16948 			return -ENOMEM;
16949 		}
16950 
16951 		freq = nla_data(
16952 		    tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
16953 
16954 		hdd_debug("freq_len=%d", freq_len);
16955 
16956 		for (i = 0; i < freq_len; i++) {
16957 			hdd_debug("freq[%d]=%d", i, freq[i]);
16958 		}
16959 
16960 		status = policy_mgr_set_sap_mandatory_channels(
16961 			hdd_ctx->psoc, freq, freq_len);
16962 		if (QDF_IS_STATUS_ERROR(status))
16963 			return -EINVAL;
16964 	}
16965 
16966 	return 0;
16967 }
16968 
16969 /**
16970  * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
16971  * @wiphy:    wiphy structure pointer
16972  * @wdev:     Wireless device structure pointer
16973  * @data:     Pointer to the data received
16974  * @data_len: Length of @data
16975  *
16976  * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
16977  * driver.
16978  * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
16979  * will initiate restart of sap.
16980  *
16981  * Return: 0 on success; errno on failure
16982  */
16983 static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
16984 		struct wireless_dev *wdev,
16985 		const void *data, int data_len)
16986 {
16987 	int errno;
16988 	struct osif_vdev_sync *vdev_sync;
16989 
16990 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
16991 	if (errno)
16992 		return errno;
16993 
16994 	errno = __wlan_hdd_cfg80211_sap_configuration_set(wiphy, wdev,
16995 							  data, data_len);
16996 
16997 	osif_vdev_sync_op_stop(vdev_sync);
16998 
16999 	return errno;
17000 }
17001 
17002 /**
17003  * wlan_hdd_process_wake_lock_stats() - wrapper function to absract cp_stats
17004  * or legacy get_wake_lock_stats API.
17005  * @hdd_ctx: pointer to hdd_ctx
17006  *
17007  * Return: 0 on success; error number otherwise.
17008  */
17009 static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
17010 {
17011 	return wlan_cfg80211_mc_cp_stats_get_wakelock_stats(hdd_ctx->psoc,
17012 							    hdd_ctx->wiphy);
17013 }
17014 
17015 /**
17016  * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
17017  * @wiphy: wiphy pointer
17018  * @wdev: pointer to struct wireless_dev
17019  * @data: pointer to incoming NL vendor data
17020  * @data_len: length of @data
17021  *
17022  * This function parses the incoming NL vendor command data attributes and
17023  * invokes the SME Api and blocks on a completion variable.
17024  * WMA copies required data and invokes callback
17025  * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
17026  *
17027  * Return: 0 on success; error number otherwise.
17028  */
17029 static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
17030 					struct wireless_dev *wdev,
17031 					const void *data,
17032 					int data_len)
17033 {
17034 	int ret;
17035 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17036 
17037 	hdd_enter();
17038 
17039 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17040 		hdd_err("Command not allowed in FTM mode");
17041 		return -EINVAL;
17042 	}
17043 
17044 	ret = wlan_hdd_validate_context(hdd_ctx);
17045 	if (0 != ret)
17046 		return -EINVAL;
17047 
17048 	ret = wlan_hdd_process_wake_lock_stats(hdd_ctx);
17049 	hdd_exit();
17050 	return ret;
17051 }
17052 
17053 /**
17054  * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
17055  * @wiphy: wiphy pointer
17056  * @wdev: pointer to struct wireless_dev
17057  * @data: pointer to incoming NL vendor data
17058  * @data_len: length of @data
17059  *
17060  * This function parses the incoming NL vendor command data attributes and
17061  * invokes the SME Api and blocks on a completion variable.
17062  * WMA copies required data and invokes callback
17063  * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
17064  *
17065  * Return: 0 on success; error number otherwise.
17066  */
17067 static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
17068 						struct wireless_dev *wdev,
17069 						const void *data, int data_len)
17070 {
17071 	struct osif_psoc_sync *psoc_sync;
17072 	int errno;
17073 
17074 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
17075 	if (errno)
17076 		return errno;
17077 
17078 	errno = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev,
17079 						       data, data_len);
17080 
17081 	osif_psoc_sync_op_stop(psoc_sync);
17082 
17083 	return errno;
17084 }
17085 
17086 /**
17087  * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
17088  * @wiphy:    wiphy structure pointer
17089  * @wdev:     Wireless device structure pointer
17090  * @data:     Pointer to the data received
17091  * @data_len: Length of @data
17092  *
17093  * This function reads wmi max bus size and fill in the skb with
17094  * NL attributes and send up the NL event.
17095  * Return: 0 on success; errno on failure
17096  */
17097 static int
17098 __wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
17099 				 struct wireless_dev *wdev,
17100 				 const void *data, int data_len)
17101 {
17102 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17103 	int ret_val;
17104 	struct sk_buff *skb;
17105 	uint32_t nl_buf_len;
17106 
17107 	hdd_enter();
17108 
17109 	ret_val = wlan_hdd_validate_context(hdd_ctx);
17110 	if (ret_val)
17111 		return ret_val;
17112 
17113 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17114 		hdd_err("Command not allowed in FTM mode");
17115 		return -EINVAL;
17116 	}
17117 
17118 	hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
17119 
17120 	nl_buf_len = NLMSG_HDRLEN;
17121 	nl_buf_len +=  (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
17122 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
17123 						       nl_buf_len);
17124 	if (!skb) {
17125 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
17126 		return -ENOMEM;
17127 	}
17128 
17129 	if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
17130 			hdd_ctx->wmi_max_len)) {
17131 		hdd_err("nla put failure");
17132 		goto nla_put_failure;
17133 	}
17134 
17135 	wlan_cfg80211_vendor_cmd_reply(skb);
17136 
17137 	hdd_exit();
17138 
17139 	return 0;
17140 
17141 nla_put_failure:
17142 	wlan_cfg80211_vendor_free_skb(skb);
17143 	return -EINVAL;
17144 }
17145 
17146 /**
17147  * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
17148  * @wiphy:    wiphy structure pointer
17149  * @wdev:     Wireless device structure pointer
17150  * @data:     Pointer to the data received
17151  * @data_len: Length of @data
17152  *
17153  * Return: 0 on success; errno on failure
17154  */
17155 static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
17156 					  struct wireless_dev *wdev,
17157 					  const void *data, int data_len)
17158 {
17159 	struct osif_psoc_sync *psoc_sync;
17160 	int errno;
17161 
17162 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
17163 	if (errno)
17164 		return errno;
17165 
17166 	errno = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
17167 
17168 	osif_psoc_sync_op_stop(psoc_sync);
17169 
17170 	return errno;
17171 }
17172 
17173 /**
17174  * __wlan_hdd_cfg80211_get_radio_combination_matrix() - get radio matrix info
17175  * @wiphy:   pointer to wireless wiphy structure.
17176  * @wdev:    pointer to wireless_dev structure.
17177  * @data:    Pointer to the data to be passed via vendor interface
17178  * @data_len:Length of the data to be passed
17179  *
17180  * Return:   Return the Success or Failure code.
17181  */
17182 static int
17183 __wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy *wiphy,
17184 						 struct wireless_dev *wdev,
17185 						 const void *data,
17186 						 int data_len)
17187 {
17188 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17189 	struct sk_buff *reply_skb;
17190 	int ret;
17191 	int skb_len;
17192 	struct nlattr *combination, *combination_cfg, *radio, *radio_comb;
17193 	uint32_t comb_num = 0;
17194 	struct radio_combination comb[MAX_RADIO_COMBINATION];
17195 	int comb_idx, radio_idx;
17196 	enum qca_set_band qca_band;
17197 
17198 	hdd_enter();
17199 
17200 	ret = wlan_hdd_validate_context(hdd_ctx);
17201 	if (ret)
17202 		return ret;
17203 
17204 	ucfg_policy_mgr_get_radio_combinations(hdd_ctx->psoc, comb,
17205 					       QDF_ARRAY_SIZE(comb),
17206 					       &comb_num);
17207 	if (!comb_num) {
17208 		hdd_err("invalid combination 0");
17209 		return -EINVAL;
17210 	}
17211 
17212 	/* band and antenna */
17213 	skb_len = nla_total_size(sizeof(uint32_t)) +
17214 		  nla_total_size(sizeof(uint8_t));
17215 	/* radio nested for max 2 MACs*/
17216 	skb_len = nla_total_size(skb_len) * MAX_MAC;
17217 	/* one radio combination */
17218 	skb_len = nla_total_size(nla_total_size(skb_len));
17219 	/* total combinations */
17220 	skb_len = nla_total_size(comb_num * nla_total_size(skb_len));
17221 	skb_len = NLMSG_HDRLEN + skb_len;
17222 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
17223 	if (!reply_skb) {
17224 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed, len %d",
17225 			skb_len);
17226 		return -EINVAL;
17227 	}
17228 
17229 	combination_cfg = nla_nest_start(reply_skb,
17230 			QCA_WLAN_VENDOR_ATTR_RADIO_MATRIX_SUPPORTED_CFGS);
17231 	if (!combination_cfg) {
17232 		ret = -ENOMEM;
17233 		goto err;
17234 	}
17235 	for (comb_idx = 0; comb_idx < comb_num; comb_idx++) {
17236 		combination = nla_nest_start(reply_skb, comb_idx);
17237 		if (!combination) {
17238 			ret = -ENOMEM;
17239 			goto err;
17240 		}
17241 		radio_comb = nla_nest_start(reply_skb,
17242 				QCA_WLAN_VENDOR_ATTR_RADIO_COMBINATIONS_CFGS);
17243 		if (!radio_comb) {
17244 			ret = -ENOMEM;
17245 			goto err;
17246 		}
17247 		for (radio_idx = 0; radio_idx < MAX_MAC; radio_idx++) {
17248 			if (!comb[comb_idx].band_mask[radio_idx])
17249 				break;
17250 			radio = nla_nest_start(reply_skb, radio_idx);
17251 			if (!radio) {
17252 				ret = -ENOMEM;
17253 				goto err;
17254 			}
17255 			if (comb[comb_idx].band_mask[radio_idx] ==
17256 							BIT(REG_BAND_5G)) {
17257 				qca_band = QCA_SETBAND_5G;
17258 			} else if (comb[comb_idx].band_mask[radio_idx] ==
17259 							BIT(REG_BAND_6G)) {
17260 				qca_band = QCA_SETBAND_6G;
17261 			} else if (comb[comb_idx].band_mask[radio_idx] ==
17262 							BIT(REG_BAND_2G)) {
17263 				qca_band = QCA_SETBAND_2G;
17264 			} else {
17265 				hdd_err("invalid band mask 0 for comb %d radio %d",
17266 					comb_idx, radio_idx);
17267 				ret = -EINVAL;
17268 				goto err;
17269 			}
17270 
17271 			if (nla_put_u32(reply_skb,
17272 				       QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_BAND,
17273 				       qca_band)) {
17274 				ret = -ENOMEM;
17275 				goto err;
17276 			}
17277 			if (nla_put_u8(reply_skb,
17278 				       QCA_WLAN_VENDOR_ATTR_SUPPORTED_RADIO_CFG_ANTENNA,
17279 				       comb[comb_idx].antenna[radio_idx])) {
17280 				ret = -ENOMEM;
17281 				goto err;
17282 			}
17283 			hdd_debug("comb[%d]:cfg[%d]: band %d, antenna %d",
17284 				  comb_idx, radio_idx, qca_band,
17285 				  comb[comb_idx].antenna[radio_idx]);
17286 			nla_nest_end(reply_skb, radio);
17287 		}
17288 		nla_nest_end(reply_skb, radio_comb);
17289 		nla_nest_end(reply_skb, combination);
17290 	}
17291 	nla_nest_end(reply_skb, combination_cfg);
17292 	return wlan_cfg80211_vendor_cmd_reply(reply_skb);
17293 
17294 err:
17295 	wlan_cfg80211_vendor_free_skb(reply_skb);
17296 	return ret;
17297 }
17298 
17299 /**
17300  * wlan_hdd_cfg80211_get_radio_combination_matrix() - get radio matrix info
17301  * @wiphy:   pointer to wireless wiphy structure.
17302  * @wdev:    pointer to wireless_dev structure.
17303  * @data:    Pointer to the data to be passed via vendor interface
17304  * @data_len:Length of the data to be passed
17305  *
17306  * Return:   Return the Success or Failure code.
17307  */
17308 static int
17309 wlan_hdd_cfg80211_get_radio_combination_matrix(struct wiphy *wiphy,
17310 					       struct wireless_dev *wdev,
17311 					       const void *data, int data_len)
17312 {
17313 	struct osif_psoc_sync *psoc_sync;
17314 	int errno;
17315 
17316 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
17317 	if (errno)
17318 		return errno;
17319 
17320 	errno = __wlan_hdd_cfg80211_get_radio_combination_matrix(wiphy, wdev,
17321 								 data,
17322 								 data_len);
17323 
17324 	osif_psoc_sync_op_stop(psoc_sync);
17325 
17326 	return errno;
17327 }
17328 
17329 const struct nla_policy setband_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
17330 	[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = {.type = NLA_U32},
17331 	[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK] = {.type = NLA_U32},
17332 };
17333 
17334 /**
17335  *__wlan_hdd_cfg80211_setband() - set band
17336  * @wiphy: Pointer to wireless phy
17337  * @wdev: Pointer to wireless device
17338  * @data: Pointer to data
17339  * @data_len: Length of @data
17340  *
17341  * Return: 0 on success, negative errno on failure
17342  */
17343 static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
17344 				       struct wireless_dev *wdev,
17345 				       const void *data, int data_len)
17346 {
17347 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17348 	struct net_device *dev = wdev->netdev;
17349 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
17350 	int ret;
17351 	uint32_t reg_wifi_band_bitmap = 0, band_val, band_mask;
17352 
17353 	hdd_enter();
17354 
17355 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
17356 		hdd_err("Command not allowed in FTM mode");
17357 		return -EPERM;
17358 	}
17359 
17360 	ret = wlan_hdd_validate_context(hdd_ctx);
17361 	if (ret)
17362 		return ret;
17363 
17364 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
17365 				    data, data_len, setband_policy)) {
17366 		hdd_err("Invalid ATTR");
17367 		return -EINVAL;
17368 	}
17369 
17370 	if (tb[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK]) {
17371 		band_mask = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_MASK]);
17372 		reg_wifi_band_bitmap =
17373 			wlan_vendor_bitmap_to_reg_wifi_band_bitmap(hdd_ctx->psoc,
17374 								   band_mask);
17375 		hdd_debug("[SET BAND] set band mask:%d", reg_wifi_band_bitmap);
17376 	} else if (tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
17377 		band_val = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]);
17378 		reg_wifi_band_bitmap =
17379 			hdd_reg_legacy_setband_to_reg_wifi_band_bitmap(
17380 								      band_val);
17381 	}
17382 
17383 	if (!reg_wifi_band_bitmap) {
17384 		hdd_err("attr SETBAND_VALUE failed");
17385 		return -EINVAL;
17386 	}
17387 
17388 	ret = hdd_reg_set_band(dev, reg_wifi_band_bitmap);
17389 
17390 	hdd_exit();
17391 	return ret;
17392 }
17393 
17394 /**
17395  * wlan_hdd_validate_acs_channel() - validate channel frequency provided by ACS
17396  * @link_info: Pointer to link_info in adapter
17397  * @chan_freq: channel frequency in MHz
17398  * @chan_bw: channel bandiodth in MHz
17399  *
17400  * return: QDF status based on success or failure
17401  */
17402 static QDF_STATUS
17403 wlan_hdd_validate_acs_channel(struct wlan_hdd_link_info *link_info,
17404 			      uint32_t chan_freq, int chan_bw)
17405 {
17406 	struct hdd_context *hdd_ctx;
17407 	struct sap_context *sap_context;
17408 
17409 	hdd_ctx = link_info->adapter->hdd_ctx;
17410 	if (QDF_STATUS_SUCCESS !=
17411 	    wlan_hdd_validate_operation_channel(hdd_ctx, chan_freq))
17412 		return QDF_STATUS_E_FAILURE;
17413 
17414 	sap_context = WLAN_HDD_GET_SAP_CTX_PTR(link_info);
17415 	if ((wlansap_is_channel_in_nol_list(sap_context, chan_freq,
17416 					    PHY_SINGLE_CHANNEL_CENTERED))) {
17417 		hdd_info("channel %d is in nol", chan_freq);
17418 		return -EINVAL;
17419 	}
17420 
17421 	if ((wlansap_is_channel_leaking_in_nol(sap_context,
17422 					       chan_freq, chan_bw))) {
17423 		hdd_info("channel freq %d is leaking in nol", chan_freq);
17424 		return -EINVAL;
17425 	}
17426 
17427 	return 0;
17428 
17429 }
17430 
17431 static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
17432 				     struct sap_config *sap_config,
17433 				     struct hdd_vendor_chan_info *channel_list)
17434 {
17435 	uint8_t ch_width;
17436 	QDF_STATUS status;
17437 	uint32_t channel_bonding_mode;
17438 
17439 	sap_config->chan_freq = channel_list->pri_chan_freq;
17440 
17441 	sap_config->ch_params.center_freq_seg0 =
17442 		wlan_reg_freq_to_chan(hdd_ctx->pdev,
17443 				      channel_list->vht_seg0_center_chan_freq);
17444 	sap_config->ch_params.center_freq_seg1 =
17445 		wlan_reg_freq_to_chan(hdd_ctx->pdev,
17446 				      channel_list->vht_seg1_center_chan_freq);
17447 
17448 	sap_config->ch_params.sec_ch_offset =
17449 		wlan_reg_freq_to_chan(hdd_ctx->pdev,
17450 				      channel_list->ht_sec_chan_freq);
17451 
17452 	sap_config->ch_params.ch_width =
17453 				hdd_map_nl_chan_width(channel_list->chan_width);
17454 	if (!WLAN_REG_IS_24GHZ_CH_FREQ(sap_config->chan_freq)) {
17455 		status =
17456 			ucfg_mlme_get_vht_channel_width(hdd_ctx->psoc,
17457 							&ch_width);
17458 		if (!QDF_IS_STATUS_SUCCESS(status))
17459 			hdd_err("Failed to set channel_width");
17460 		sap_config->ch_width_orig = ch_width;
17461 	} else {
17462 		ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
17463 						    &channel_bonding_mode);
17464 		sap_config->ch_width_orig = channel_bonding_mode ?
17465 			CH_WIDTH_40MHZ : CH_WIDTH_20MHZ;
17466 	}
17467 	sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
17468 	sap_config->acs_cfg.ch_width =
17469 				hdd_map_nl_chan_width(channel_list->chan_width);
17470 	sap_config->acs_cfg.vht_seg0_center_ch_freq =
17471 			channel_list->vht_seg0_center_chan_freq;
17472 	sap_config->acs_cfg.vht_seg1_center_ch_freq =
17473 			channel_list->vht_seg1_center_chan_freq;
17474 	sap_config->acs_cfg.ht_sec_ch_freq =
17475 			channel_list->ht_sec_chan_freq;
17476 }
17477 
17478 static int hdd_update_acs_channel(struct wlan_hdd_link_info *link_info,
17479 				  uint8_t reason, uint8_t channel_cnt,
17480 				  struct hdd_vendor_chan_info *channel_list)
17481 {
17482 	struct sap_config *sap_config;
17483 	struct hdd_ap_ctx *hdd_ap_ctx;
17484 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
17485 	QDF_STATUS status = QDF_STATUS_SUCCESS;
17486 	mac_handle_t mac_handle;
17487 	uint32_t ch;
17488 
17489 	if (!channel_list) {
17490 		hdd_err("channel_list is NULL");
17491 		return -EINVAL;
17492 	}
17493 
17494 	hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
17495 	sap_config = &link_info->session.ap.sap_config;
17496 
17497 	if (QDF_TIMER_STATE_RUNNING ==
17498 	    qdf_mc_timer_get_current_state(&hdd_ap_ctx->vendor_acs_timer)) {
17499 		qdf_mc_timer_stop(&hdd_ap_ctx->vendor_acs_timer);
17500 	}
17501 
17502 	if (channel_list->pri_chan_freq == 0) {
17503 		/* Check mode, set default channel */
17504 		channel_list->pri_chan_freq = 2437;
17505 		/*
17506 		 * sap_select_default_oper_chan(mac_handle,
17507 		 *      sap_config->acs_cfg.hw_mode);
17508 		 */
17509 	}
17510 
17511 	mac_handle = hdd_ctx->mac_handle;
17512 	switch (reason) {
17513 	/* SAP init case */
17514 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
17515 		hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
17516 		/* Update Hostapd */
17517 		wlan_hdd_cfg80211_acs_ch_select_evt(link_info, true);
17518 		break;
17519 
17520 	/* DFS detected on current channel */
17521 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
17522 		ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
17523 					   channel_list->pri_chan_freq);
17524 
17525 		wlan_sap_update_next_channel(
17526 			WLAN_HDD_GET_SAP_CTX_PTR(link_info), (uint8_t)ch,
17527 			hdd_map_nl_chan_width(channel_list->chan_width));
17528 		status = sme_update_new_channel_event(
17529 					mac_handle, link_info->vdev_id);
17530 		break;
17531 
17532 	/* LTE coex event on current channel */
17533 	case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
17534 		ch = wlan_reg_freq_to_chan(hdd_ctx->pdev,
17535 					   channel_list->pri_chan_freq);
17536 		sap_config->acs_cfg.pri_ch_freq = channel_list->pri_chan_freq;
17537 		sap_config->acs_cfg.ch_width =
17538 				hdd_map_nl_chan_width(channel_list->chan_width);
17539 		hdd_ap_ctx->sap_config.ch_width_orig =
17540 				sap_config->acs_cfg.ch_width;
17541 		wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc,
17542 					    link_info->vdev_id,
17543 					    CSA_REASON_LTE_COEX);
17544 		hdd_switch_sap_channel(link_info, (uint8_t)ch, true);
17545 		break;
17546 
17547 	default:
17548 		hdd_info("invalid reason for timer invoke");
17549 	}
17550 	hdd_exit();
17551 	return qdf_status_to_os_return(status);
17552 }
17553 
17554 /*
17555  * Define short name for vendor channel set config
17556  */
17557 #define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
17558 #define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
17559 #define SET_CHAN_PRIMARY_CHANNEL \
17560 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
17561 #define SET_CHAN_SECONDARY_CHANNEL \
17562 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
17563 #define SET_CHAN_SEG0_CENTER_CHANNEL \
17564 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
17565 #define	SET_CHAN_SEG1_CENTER_CHANNEL \
17566 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
17567 #define	SET_CHAN_CHANNEL_WIDTH \
17568 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
17569 
17570 #define SET_CHAN_FREQ_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST
17571 #define SET_CHAN_FREQUENCY_PRIMARY \
17572 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY
17573 #define SET_CHAN_FREQUENCY_SECONDARY \
17574 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY
17575 #define SET_CHAN_SEG0_CENTER_FREQUENCY \
17576 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0
17577 #define SET_CHAN_SEG1_CENTER_FREQUENCY \
17578 	QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1
17579 
17580 #define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
17581 #define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
17582 
17583 static const struct nla_policy acs_chan_config_policy[SET_CHAN_MAX + 1] = {
17584 	[SET_CHAN_REASON] = {.type = NLA_U8},
17585 	[SET_CHAN_CHAN_LIST] = {.type = NLA_NESTED},
17586 	[SET_CHAN_FREQ_LIST] = {.type = NLA_NESTED},
17587 };
17588 
17589 static const struct nla_policy acs_chan_list_policy[SET_CHAN_MAX + 1] = {
17590 	[SET_CHAN_PRIMARY_CHANNEL] = {.type = NLA_U8},
17591 	[SET_CHAN_SECONDARY_CHANNEL] = {.type = NLA_U8},
17592 	[SET_CHAN_SEG0_CENTER_CHANNEL] = {.type = NLA_U8},
17593 	[SET_CHAN_SEG1_CENTER_CHANNEL] = {.type = NLA_U8},
17594 	[SET_CHAN_CHANNEL_WIDTH] = {.type = NLA_U8},
17595 	[SET_EXT_ACS_BAND] = {.type = NLA_U8},
17596 
17597 	[SET_CHAN_FREQUENCY_PRIMARY] = {.type = NLA_U32},
17598 	[SET_CHAN_FREQUENCY_SECONDARY] = {.type = NLA_U32},
17599 	[SET_CHAN_SEG0_CENTER_FREQUENCY] = {.type = NLA_U32},
17600 	[SET_CHAN_SEG1_CENTER_FREQUENCY] = {.type = NLA_U32},
17601 };
17602 
17603 /**
17604  * hdd_extract_external_acs_frequencies() - API to parse and extract vendor acs
17605  * channel frequency (in MHz) configuration.
17606  * @hdd_ctx: pointer to hdd context
17607  * @list_ptr: pointer to hdd_vendor_chan_info
17608  * @channel_cnt: channel count
17609  * @data: data
17610  * @data_len: data len
17611  *
17612  * Return: 0 on success, negative errno on failure
17613  */
17614 static int
17615 hdd_extract_external_acs_frequencies(struct hdd_context *hdd_ctx,
17616 				     struct hdd_vendor_chan_info **list_ptr,
17617 				     uint8_t *channel_cnt,
17618 				     const void *data, int data_len)
17619 {
17620 	int rem;
17621 	uint32_t i = 0;
17622 	struct nlattr *tb[SET_CHAN_MAX + 1];
17623 	struct nlattr *tb2[SET_CHAN_MAX + 1];
17624 	struct nlattr *curr_attr;
17625 	struct hdd_vendor_chan_info *channel_list;
17626 
17627 	if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
17628 				    acs_chan_config_policy)) {
17629 		hdd_err("Invalid ATTR");
17630 		return -EINVAL;
17631 	}
17632 
17633 	nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem)
17634 		i++;
17635 
17636 	if (!i) {
17637 		hdd_err_rl("Error: channel count is zero");
17638 		return -EINVAL;
17639 	}
17640 
17641 	if (i > NUM_CHANNELS) {
17642 		hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
17643 		return -ENOMEM;
17644 	}
17645 
17646 	channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
17647 	if (!channel_list)
17648 		return -ENOMEM;
17649 
17650 	*channel_cnt = (uint8_t)i;
17651 	i = 0;
17652 	nla_for_each_nested(curr_attr, tb[SET_CHAN_FREQ_LIST], rem) {
17653 		if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
17654 						   curr_attr,
17655 						   acs_chan_list_policy)) {
17656 			hdd_err_rl("nla_parse failed");
17657 			qdf_mem_free(channel_list);
17658 			*channel_cnt = 0;
17659 			return -EINVAL;
17660 		}
17661 
17662 		if (tb2[SET_EXT_ACS_BAND])
17663 			channel_list[i].band =
17664 				nla_get_u8(tb2[SET_EXT_ACS_BAND]);
17665 
17666 		if (tb2[SET_CHAN_FREQUENCY_PRIMARY])
17667 			channel_list[i].pri_chan_freq =
17668 				nla_get_u32(tb2[SET_CHAN_FREQUENCY_PRIMARY]);
17669 
17670 		if (tb2[SET_CHAN_FREQUENCY_SECONDARY])
17671 			channel_list[i].ht_sec_chan_freq =
17672 				nla_get_u32(tb2[SET_CHAN_FREQUENCY_SECONDARY]);
17673 
17674 		if (tb2[SET_CHAN_SEG0_CENTER_FREQUENCY])
17675 			channel_list[i].vht_seg0_center_chan_freq =
17676 			 nla_get_u32(tb2[SET_CHAN_SEG0_CENTER_FREQUENCY]);
17677 
17678 		if (tb2[SET_CHAN_SEG1_CENTER_FREQUENCY])
17679 			channel_list[i].vht_seg1_center_chan_freq =
17680 			 nla_get_u32(tb2[SET_CHAN_SEG1_CENTER_FREQUENCY]);
17681 
17682 		if (tb2[SET_CHAN_CHANNEL_WIDTH])
17683 			channel_list[i].chan_width =
17684 				nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
17685 
17686 		hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
17687 			  i, channel_list[i].pri_chan_freq,
17688 			  channel_list[i].ht_sec_chan_freq,
17689 			  channel_list[i].vht_seg0_center_chan_freq,
17690 			  channel_list[i].vht_seg1_center_chan_freq,
17691 			  channel_list[i].chan_width);
17692 		i++;
17693 	}
17694 	*list_ptr = channel_list;
17695 
17696 	return 0;
17697 }
17698 
17699 /**
17700  * hdd_extract_external_acs_channels() - API to parse and extract vendor acs
17701  * channel configuration.
17702  * @hdd_ctx: pointer to hdd context
17703  * @list_ptr: pointer to hdd_vendor_chan_info
17704  * @channel_cnt: channel count
17705  * @data: data
17706  * @data_len: data len
17707  *
17708  * Return: 0 on success, negative errno on failure
17709  */
17710 static int
17711 hdd_extract_external_acs_channels(struct hdd_context *hdd_ctx,
17712 				  struct hdd_vendor_chan_info **list_ptr,
17713 				  uint8_t *channel_cnt,
17714 				  const void *data, int data_len)
17715 {
17716 	int rem;
17717 	uint32_t i = 0;
17718 	struct nlattr *tb[SET_CHAN_MAX + 1];
17719 	struct nlattr *tb2[SET_CHAN_MAX + 1];
17720 	struct nlattr *curr_attr;
17721 	struct hdd_vendor_chan_info *channel_list;
17722 
17723 	if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
17724 				    acs_chan_config_policy)) {
17725 		hdd_err("Invalid ATTR");
17726 		return -EINVAL;
17727 	}
17728 
17729 	nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
17730 		i++;
17731 
17732 	if (!i) {
17733 		hdd_err_rl("Error: channel count is zero");
17734 		return -EINVAL;
17735 	}
17736 
17737 	if (i > NUM_CHANNELS) {
17738 		hdd_err_rl("Error: Exceeded max channels: %u", NUM_CHANNELS);
17739 		return -ENOMEM;
17740 	}
17741 
17742 	channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) * i);
17743 	if (!channel_list)
17744 		return -ENOMEM;
17745 
17746 	*channel_cnt = (uint8_t)i;
17747 	i = 0;
17748 	nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
17749 		if (wlan_cfg80211_nla_parse_nested(tb2, SET_CHAN_MAX,
17750 						   curr_attr,
17751 						   acs_chan_list_policy)) {
17752 			hdd_err("nla_parse failed");
17753 			qdf_mem_free(channel_list);
17754 			*channel_cnt = 0;
17755 			return -EINVAL;
17756 		}
17757 
17758 		if (tb2[SET_EXT_ACS_BAND]) {
17759 			channel_list[i].band =
17760 				nla_get_u8(tb2[SET_EXT_ACS_BAND]);
17761 		}
17762 
17763 		if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
17764 			uint32_t ch =
17765 				nla_get_u8(tb2[SET_CHAN_PRIMARY_CHANNEL]);
17766 
17767 			channel_list[i].pri_chan_freq =
17768 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
17769 		}
17770 
17771 		if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
17772 			uint32_t ch =
17773 				nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
17774 
17775 			channel_list[i].ht_sec_chan_freq =
17776 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
17777 		}
17778 
17779 		if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
17780 			uint32_t ch =
17781 				nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
17782 
17783 			channel_list[i].vht_seg0_center_chan_freq =
17784 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
17785 		}
17786 
17787 		if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
17788 			uint32_t ch =
17789 				nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
17790 
17791 			channel_list[i].vht_seg1_center_chan_freq =
17792 				wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev, ch);
17793 		}
17794 
17795 		if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
17796 			channel_list[i].chan_width =
17797 				nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
17798 		}
17799 		hdd_debug("index %d, pri_chan_freq %u, ht_sec_chan_freq %u seg0_freq %u seg1_freq %u width %u",
17800 			  i, channel_list[i].pri_chan_freq,
17801 			  channel_list[i].ht_sec_chan_freq,
17802 			  channel_list[i].vht_seg0_center_chan_freq,
17803 			  channel_list[i].vht_seg1_center_chan_freq,
17804 			  channel_list[i].chan_width);
17805 		i++;
17806 	}
17807 	*list_ptr = channel_list;
17808 
17809 	return 0;
17810 }
17811 
17812 /**
17813  * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
17814  * @hdd_ctx: pointer to hdd context
17815  * @chan_list_ptr: pointer to hdd_vendor_chan_info
17816  * @reason: channel change reason
17817  * @channel_cnt: channel count
17818  * @data: data
17819  * @data_len: data len
17820  *
17821  * Return: 0 on success, negative errno on failure
17822  */
17823 static int
17824 hdd_parse_vendor_acs_chan_config(struct hdd_context *hdd_ctx,
17825 				 struct hdd_vendor_chan_info **chan_list_ptr,
17826 				 uint8_t *reason, uint8_t *channel_cnt,
17827 				 const void *data, int data_len)
17828 {
17829 	struct nlattr *tb[SET_CHAN_MAX + 1];
17830 	int ret;
17831 
17832 	if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len,
17833 				    acs_chan_config_policy)) {
17834 		hdd_err("Invalid ATTR");
17835 		return -EINVAL;
17836 	}
17837 
17838 	if (tb[SET_CHAN_REASON])
17839 		*reason = nla_get_u8(tb[SET_CHAN_REASON]);
17840 
17841 	if (!tb[SET_CHAN_FREQ_LIST] && !tb[SET_CHAN_CHAN_LIST]) {
17842 		hdd_err("Both channel list and frequency list are empty");
17843 		return -EINVAL;
17844 	}
17845 
17846 	if (tb[SET_CHAN_FREQ_LIST]) {
17847 		ret = hdd_extract_external_acs_frequencies(hdd_ctx,
17848 							   chan_list_ptr,
17849 							   channel_cnt,
17850 							   data, data_len);
17851 		if (ret) {
17852 			hdd_err("Failed to extract frequencies");
17853 			return ret;
17854 		}
17855 
17856 		return 0;
17857 	}
17858 
17859 	ret = hdd_extract_external_acs_channels(hdd_ctx, chan_list_ptr,
17860 						channel_cnt, data, data_len);
17861 	if (ret)
17862 		hdd_err("Failed to extract channels");
17863 
17864 	return ret;
17865 }
17866 
17867 /*
17868  * Undef short names for vendor set channel configuration
17869  */
17870 #undef SET_CHAN_REASON
17871 #undef SET_CHAN_CHAN_LIST
17872 #undef SET_CHAN_PRIMARY_CHANNEL
17873 #undef SET_CHAN_SECONDARY_CHANNEL
17874 #undef SET_CHAN_SEG0_CENTER_CHANNEL
17875 #undef SET_CHAN_SEG1_CENTER_CHANNEL
17876 
17877 #undef SET_CHAN_FREQ_LIST
17878 #undef SET_CHAN_FREQUENCY_PRIMARY
17879 #undef SET_CHAN_FREQUENCY_SECONDARY
17880 #undef SET_CHAN_SEG0_CENTER_FREQUENCY
17881 #undef SET_CHAN_SEG1_CENTER_FREQUENCY
17882 
17883 #undef SET_CHAN_CHANNEL_WIDTH
17884 #undef SET_CHAN_MAX
17885 
17886 /**
17887  * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
17888  * @wiphy: Pointer to wireless phy
17889  * @wdev: Pointer to wireless device
17890  * @data: Pointer to data
17891  * @data_len: Length of @data
17892  *
17893  * Return: 0 on success, negative errno on failure
17894  */
17895 static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
17896 						     struct wireless_dev *wdev,
17897 						     const void *data,
17898 						     int data_len)
17899 {
17900 	int ret_val;
17901 	QDF_STATUS status;
17902 	enum phy_ch_width phy_ch_width;
17903 	uint8_t channel_cnt = 0, reason = -1;
17904 	struct hdd_vendor_chan_info *chan_list = NULL;
17905 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
17906 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
17907 	struct hdd_vendor_chan_info *chan_list_ptr;
17908 	struct wlan_hdd_link_info *link_info = adapter->deflink;
17909 
17910 	hdd_enter();
17911 
17912 	ret_val = wlan_hdd_validate_context(hdd_ctx);
17913 	if (ret_val)
17914 		return ret_val;
17915 
17916 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
17917 		hdd_err("Command not allowed in FTM mode");
17918 		return -EINVAL;
17919 	}
17920 
17921 	if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &link_info->link_flags)) {
17922 		clear_bit(VENDOR_ACS_RESPONSE_PENDING, &link_info->link_flags);
17923 	} else {
17924 		hdd_err("already timeout happened for acs");
17925 		return -EINVAL;
17926 	}
17927 
17928 	ret_val = hdd_parse_vendor_acs_chan_config(hdd_ctx, &chan_list,
17929 						   &reason, &channel_cnt, data,
17930 						   data_len);
17931 	chan_list_ptr = chan_list;
17932 	if (ret_val)
17933 		return ret_val;
17934 
17935 	/* Validate channel to be set */
17936 	while (channel_cnt && chan_list) {
17937 		phy_ch_width = hdd_map_nl_chan_width(chan_list->chan_width);
17938 		status = wlan_hdd_validate_acs_channel(link_info,
17939 						       chan_list->pri_chan_freq,
17940 						       phy_ch_width);
17941 		if (status == QDF_STATUS_SUCCESS)
17942 			break;
17943 		else if (channel_cnt == 1) {
17944 			hdd_err("invalid channel frequ %u received from app",
17945 				chan_list->pri_chan_freq);
17946 			chan_list->pri_chan_freq = 0;
17947 			break;
17948 		}
17949 
17950 		channel_cnt--;
17951 		chan_list++;
17952 	}
17953 
17954 	if ((channel_cnt <= 0) || !chan_list) {
17955 		hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
17956 			chan_list);
17957 		qdf_mem_free(chan_list_ptr);
17958 		return -EINVAL;
17959 	}
17960 
17961 	hdd_debug("received primary channel freq as %d",
17962 		  chan_list->pri_chan_freq);
17963 
17964 	ret_val = hdd_update_acs_channel(link_info, reason,
17965 					 channel_cnt, chan_list);
17966 	qdf_mem_free(chan_list_ptr);
17967 	return ret_val;
17968 }
17969 
17970 /**
17971  * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
17972  * @wiphy: Pointer to wireless phy
17973  * @wdev: Pointer to wireless device
17974  * @data: Pointer to data
17975  * @data_len: Length of @data
17976  *
17977  * Return: 0 on success, negative errno on failure
17978  */
17979 static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
17980 						struct wireless_dev *wdev,
17981 						const void *data, int data_len)
17982 {
17983 	int errno;
17984 	struct osif_vdev_sync *vdev_sync;
17985 
17986 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
17987 	if (errno)
17988 		return errno;
17989 
17990 	errno = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev,
17991 							  data, data_len);
17992 
17993 	osif_vdev_sync_op_stop(vdev_sync);
17994 
17995 	return errno;
17996 }
17997 
17998 /**
17999  * wlan_hdd_cfg80211_setband() - Wrapper to setband
18000  * @wiphy:    wiphy structure pointer
18001  * @wdev:     Wireless device structure pointer
18002  * @data:     Pointer to the data received
18003  * @data_len: Length of @data
18004  *
18005  * Return: 0 on success; errno on failure
18006  */
18007 static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
18008 				    struct wireless_dev *wdev,
18009 				    const void *data, int data_len)
18010 {
18011 	int errno;
18012 	struct osif_vdev_sync *vdev_sync;
18013 
18014 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18015 	if (errno)
18016 		return errno;
18017 
18018 	errno = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
18019 
18020 	osif_vdev_sync_op_stop(vdev_sync);
18021 
18022 	return errno;
18023 }
18024 
18025 /**
18026  *__wlan_hdd_cfg80211_getband() - get band
18027  * @wiphy: Pointer to wireless phy
18028  * @wdev: Pointer to wireless device
18029  * @data: Pointer to data
18030  * @data_len: Length of @data
18031  *
18032  * Return: 0 on success, negative errno on failure
18033  */
18034 static int __wlan_hdd_cfg80211_getband(struct wiphy *wiphy,
18035 				       struct wireless_dev *wdev,
18036 				       const void *data, int data_len)
18037 {
18038 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18039 	struct sk_buff *skb;
18040 	QDF_STATUS status = QDF_STATUS_SUCCESS;
18041 	int ret;
18042 	uint32_t reg_wifi_band_bitmap, vendor_band_mask;
18043 
18044 	hdd_enter();
18045 
18046 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18047 		hdd_err("Command not allowed in FTM mode");
18048 		return -EPERM;
18049 	}
18050 
18051 	ret = wlan_hdd_validate_context(hdd_ctx);
18052 	if (ret)
18053 		return ret;
18054 
18055 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
18056 						       sizeof(uint32_t) +
18057 						       NLA_HDRLEN);
18058 
18059 	if (!skb) {
18060 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
18061 		return -ENOMEM;
18062 	}
18063 
18064 	status = ucfg_reg_get_band(hdd_ctx->pdev, &reg_wifi_band_bitmap);
18065 	if (!QDF_IS_STATUS_SUCCESS(status)) {
18066 		hdd_err("failed to get band");
18067 		goto failure;
18068 	}
18069 
18070 	vendor_band_mask = wlan_reg_wifi_band_bitmap_to_vendor_bitmap(
18071 							reg_wifi_band_bitmap);
18072 
18073 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_SETBAND_MASK,
18074 			vendor_band_mask)) {
18075 		hdd_err("nla put failure");
18076 		goto failure;
18077 	}
18078 
18079 	wlan_cfg80211_vendor_cmd_reply(skb);
18080 
18081 	hdd_exit();
18082 
18083 	return 0;
18084 
18085 failure:
18086 	wlan_cfg80211_vendor_free_skb(skb);
18087 	return -EINVAL;
18088 }
18089 
18090 /**
18091  * wlan_hdd_cfg80211_getband() - Wrapper to getband
18092  * @wiphy:    wiphy structure pointer
18093  * @wdev:     Wireless device structure pointer
18094  * @data:     Pointer to the data received
18095  * @data_len: Length of @data
18096  *
18097  * Return: 0 on success; errno on failure
18098  */
18099 static int wlan_hdd_cfg80211_getband(struct wiphy *wiphy,
18100 				     struct wireless_dev *wdev,
18101 				     const void *data, int data_len)
18102 {
18103 	int errno;
18104 	struct osif_vdev_sync *vdev_sync;
18105 
18106 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18107 	if (errno)
18108 		return errno;
18109 
18110 	errno = __wlan_hdd_cfg80211_getband(wiphy, wdev, data, data_len);
18111 
18112 	osif_vdev_sync_op_stop(vdev_sync);
18113 
18114 	return errno;
18115 }
18116 
18117 static const struct
18118 nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
18119 	[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
18120 	[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]       = {.type = NLA_BINARY,
18121 						 .len = QDF_MAC_ADDR_SIZE},
18122 };
18123 
18124 void wlan_hdd_rso_cmd_status_cb(hdd_handle_t hdd_handle,
18125 				struct rso_cmd_status *rso_status)
18126 {
18127 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
18128 	struct wlan_hdd_link_info *link_info;
18129 
18130 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, rso_status->vdev_id);
18131 	if (!link_info) {
18132 		hdd_err("Invalid vdev");
18133 		return;
18134 	}
18135 
18136 	link_info->adapter->lfr_fw_status.is_disabled = rso_status->status;
18137 	complete(&link_info->adapter->lfr_fw_status.disable_lfr_event);
18138 }
18139 
18140 /**
18141  * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
18142  * @wiphy: Pointer to wireless phy
18143  * @wdev: Pointer to wireless device
18144  * @data: Pointer to data
18145  * @data_len: Length of @data
18146  *
18147  * This function is used to enable/disable roaming using vendor commands
18148  *
18149  * Return: 0 on success, negative errno on failure
18150  */
18151 static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
18152 						struct wireless_dev *wdev,
18153 						const void *data, int data_len)
18154 {
18155 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18156 	struct net_device *dev = wdev->netdev;
18157 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18158 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
18159 	uint32_t is_fast_roam_enabled;
18160 	int ret;
18161 	QDF_STATUS qdf_status;
18162 	unsigned long rc;
18163 	bool roaming_enabled;
18164 
18165 	hdd_enter_dev(dev);
18166 
18167 	ret = wlan_hdd_validate_context(hdd_ctx);
18168 	if (0 != ret)
18169 		return ret;
18170 
18171 	if (adapter->device_mode != QDF_STA_MODE) {
18172 		hdd_err_rl("command not allowed in %d mode, vdev_id: %d",
18173 			   adapter->device_mode, adapter->deflink->vdev_id);
18174 		return -EINVAL;
18175 	}
18176 
18177 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18178 		hdd_err("Command not allowed in FTM mode");
18179 		return -EINVAL;
18180 	}
18181 
18182 	ret = wlan_cfg80211_nla_parse(tb,
18183 				      QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
18184 				      qca_wlan_vendor_attr);
18185 	if (ret) {
18186 		hdd_err("Invalid ATTR");
18187 		return -EINVAL;
18188 	}
18189 
18190 	/* Parse and fetch Enable flag */
18191 	if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
18192 		hdd_err("attr enable failed");
18193 		return -EINVAL;
18194 	}
18195 
18196 	is_fast_roam_enabled = nla_get_u32(
18197 				tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
18198 	hdd_debug("ROAM_CONFIG: isFastRoamEnabled %d", is_fast_roam_enabled);
18199 
18200 	if (sme_roaming_in_progress(hdd_ctx->mac_handle,
18201 				    adapter->deflink->vdev_id)) {
18202 		hdd_err_rl("Roaming in progress for vdev %d",
18203 			   adapter->deflink->vdev_id);
18204 		return -EAGAIN;
18205 	}
18206 
18207 	/*
18208 	 * Get current roaming state and decide whether to wait for RSO_STOP
18209 	 * response or not.
18210 	 */
18211 	roaming_enabled = ucfg_is_rso_enabled(hdd_ctx->pdev,
18212 					      adapter->deflink->vdev_id);
18213 
18214 	/* Update roaming */
18215 	qdf_status = ucfg_user_space_enable_disable_rso(
18216 						hdd_ctx->pdev,
18217 						adapter->deflink->vdev_id,
18218 						is_fast_roam_enabled);
18219 	if (QDF_IS_STATUS_ERROR(qdf_status))
18220 		hdd_err("ROAM_CONFIG: sme_config_fast_roaming failed with status=%d",
18221 			qdf_status);
18222 
18223 	ret = qdf_status_to_os_return(qdf_status);
18224 
18225 	if (hdd_cm_is_vdev_associated(adapter->deflink) &&
18226 	    roaming_enabled &&
18227 	    QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
18228 		INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
18229 		/*
18230 		 * wait only for LFR disable in fw as LFR enable
18231 		 * is always success
18232 		 */
18233 		rc = wait_for_completion_timeout(
18234 				&adapter->lfr_fw_status.disable_lfr_event,
18235 				msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
18236 		if (!rc) {
18237 			hdd_err("Timed out waiting for RSO CMD status");
18238 			return -ETIMEDOUT;
18239 		}
18240 
18241 		if (!adapter->lfr_fw_status.is_disabled) {
18242 			hdd_err("Roam disable attempt in FW fails");
18243 			return -EBUSY;
18244 		}
18245 	}
18246 
18247 	hdd_exit();
18248 	return ret;
18249 }
18250 
18251 /**
18252  * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
18253  * @wiphy: Pointer to wireless phy
18254  * @wdev: Pointer to wireless device
18255  * @data: Pointer to data
18256  * @data_len: Length of @data
18257  *
18258  * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
18259  *
18260  * Return: 0 on success, negative errno on failure
18261  */
18262 static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
18263 					  struct wireless_dev *wdev,
18264 					  const void *data, int data_len)
18265 {
18266 	int errno;
18267 	struct osif_vdev_sync *vdev_sync;
18268 
18269 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18270 	if (errno)
18271 		return errno;
18272 
18273 	errno = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev,
18274 						     data, data_len);
18275 
18276 	osif_vdev_sync_op_stop(vdev_sync);
18277 
18278 	return errno;
18279 }
18280 
18281 /*
18282  * define short names for the global vendor params
18283  * used by wlan_hdd_cfg80211_setarp_stats_cmd()
18284  */
18285 #define STATS_SET_INVALID \
18286 	QCA_ATTR_NUD_STATS_SET_INVALID
18287 #define STATS_SET_START \
18288 	QCA_ATTR_NUD_STATS_SET_START
18289 #define STATS_GW_IPV4 \
18290 	QCA_ATTR_NUD_STATS_GW_IPV4
18291 #define STATS_SET_DATA_PKT_INFO \
18292 		QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
18293 #define STATS_SET_MAX \
18294 	QCA_ATTR_NUD_STATS_SET_MAX
18295 
18296 const struct nla_policy
18297 qca_wlan_vendor_set_nud_stats_policy[STATS_SET_MAX + 1] = {
18298 	[STATS_SET_START] = {.type = NLA_FLAG },
18299 	[STATS_GW_IPV4] = {.type = NLA_U32 },
18300 	[STATS_SET_DATA_PKT_INFO] = {.type = NLA_NESTED },
18301 };
18302 
18303 /* define short names for the global vendor params */
18304 #define CONNECTIVITY_STATS_SET_INVALID \
18305 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
18306 #define STATS_PKT_INFO_TYPE \
18307 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
18308 #define STATS_DNS_DOMAIN_NAME \
18309 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
18310 #define STATS_SRC_PORT \
18311 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
18312 #define STATS_DEST_PORT \
18313 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
18314 #define STATS_DEST_IPV4 \
18315 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
18316 #define STATS_DEST_IPV6 \
18317 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
18318 #define CONNECTIVITY_STATS_SET_MAX \
18319 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
18320 
18321 const struct nla_policy
18322 qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
18323 	[STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
18324 	[STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
18325 					.len = DNS_DOMAIN_NAME_MAX_LEN },
18326 	[STATS_SRC_PORT] = {.type = NLA_U32 },
18327 	[STATS_DEST_PORT] = {.type = NLA_U32 },
18328 	[STATS_DEST_IPV4] = {.type = NLA_U32 },
18329 	[STATS_DEST_IPV6] = {.type = NLA_BINARY,
18330 					.len = ICMPv6_ADDR_LEN },
18331 };
18332 
18333 const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
18334 		QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
18335 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] =
18336 	VENDOR_NLA_POLICY_NESTED(qca_wlan_vendor_set_trace_level_policy),
18337 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
18338 	[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
18339 };
18340 
18341 /**
18342  * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
18343  * @wiphy: Pointer to wireless phy
18344  * @wdev: Pointer to wireless device
18345  * @data: Pointer to data
18346  * @data_len: Length of @data
18347  *
18348  * Return: 0 on success, negative errno on failure
18349  */
18350 static int
18351 __wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
18352 					struct wireless_dev *wdev,
18353 					const void *data,
18354 					int data_len)
18355 {
18356 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18357 	struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
18358 	struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
18359 	struct nlattr *apth;
18360 	int rem;
18361 	int ret = 1;
18362 	int print_idx = -1;
18363 	int module_id = -1;
18364 	int bit_mask = -1;
18365 	int status;
18366 
18367 	hdd_enter();
18368 
18369 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
18370 		hdd_err("Command not allowed in FTM mode");
18371 		return -EINVAL;
18372 	}
18373 
18374 	ret = wlan_hdd_validate_context(hdd_ctx);
18375 	if (ret != 0)
18376 		return -EINVAL;
18377 
18378 	print_idx = qdf_get_pidx();
18379 	if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
18380 		hdd_err("Invalid print control object index");
18381 		return -EINVAL;
18382 	}
18383 
18384 	if (wlan_cfg80211_nla_parse(tb1,
18385 				    QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
18386 				    data, data_len,
18387 				    qca_wlan_vendor_set_trace_level_policy)) {
18388 		hdd_err("Invalid attr");
18389 		return -EINVAL;
18390 	}
18391 
18392 	if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
18393 		hdd_err("attr trace level param failed");
18394 		return -EINVAL;
18395 	}
18396 
18397 	nla_for_each_nested(apth,
18398 			tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
18399 		if (wlan_cfg80211_nla_parse(tb2,
18400 				     QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
18401 				     nla_data(apth), nla_len(apth),
18402 				     qca_wlan_vendor_set_trace_level_policy)) {
18403 			hdd_err("Invalid attr");
18404 			return -EINVAL;
18405 		}
18406 
18407 		if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
18408 			hdd_err("attr Module ID failed");
18409 			return -EINVAL;
18410 		}
18411 		module_id = nla_get_u32
18412 			(tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
18413 
18414 		if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
18415 			hdd_err("attr Verbose mask failed");
18416 			return -EINVAL;
18417 		}
18418 		bit_mask = nla_get_u32
18419 		      (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
18420 
18421 		status = hdd_qdf_trace_enable(module_id, bit_mask);
18422 
18423 		if (status != 0)
18424 			hdd_err("can not set verbose mask %d for the category %d",
18425 				bit_mask, module_id);
18426 	}
18427 
18428 	hdd_exit();
18429 	return ret;
18430 }
18431 
18432 /**
18433  * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
18434  * @wiphy: Pointer to wireless phy
18435  * @wdev: Pointer to wireless device
18436  * @data: Pointer to data
18437  * @data_len: Length of @data
18438  *
18439  * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
18440  *
18441  * Return: 0 on success, negative errno on failure
18442  */
18443 
18444 static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
18445 						struct wireless_dev *wdev,
18446 						const void *data,
18447 						int data_len)
18448 {
18449 	struct osif_psoc_sync *psoc_sync;
18450 	int errno;
18451 
18452 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
18453 	if (errno)
18454 		return errno;
18455 
18456 	errno = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev,
18457 						    data, data_len);
18458 
18459 	osif_psoc_sync_op_stop(psoc_sync);
18460 
18461 	return errno;
18462 }
18463 
18464 /**
18465  * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
18466  * @wiphy: pointer to wireless wiphy structure.
18467  * @wdev: pointer to wireless_dev structure.
18468  * @data: pointer to apfind configuration data.
18469  * @data_len: the length in byte of apfind data.
18470  *
18471  * This is called when wlan driver needs to send arp stats to
18472  * firmware.
18473  *
18474  * Return: An error code or 0 on success.
18475  */
18476 static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
18477 					     struct wireless_dev *wdev,
18478 					     const void *data, int data_len)
18479 {
18480 	struct net_device   *dev = wdev->netdev;
18481 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18482 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18483 	struct wlan_objmgr_vdev *vdev;
18484 	int err = 0;
18485 
18486 	hdd_enter();
18487 
18488 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18489 		hdd_err("Command not allowed in FTM mode");
18490 		return -EINVAL;
18491 	}
18492 
18493 	err = wlan_hdd_validate_context(hdd_ctx);
18494 	if (0 != err)
18495 		return err;
18496 
18497 	if (adapter->deflink->vdev_id == WLAN_UMAC_VDEV_ID_MAX) {
18498 		hdd_err("Invalid vdev id");
18499 		return -EINVAL;
18500 	}
18501 
18502 	if (adapter->device_mode != QDF_STA_MODE) {
18503 		hdd_err("STATS supported in only STA mode!");
18504 		return -EINVAL;
18505 	}
18506 
18507 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
18508 		hdd_debug("Not Associated");
18509 		return 0;
18510 	}
18511 
18512 	if (hdd_is_roaming_in_progress(hdd_ctx))
18513 		return -EINVAL;
18514 
18515 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
18516 	if (!vdev)
18517 		return -EINVAL;
18518 
18519 	err = osif_dp_set_nud_stats(wiphy, vdev, data, data_len);
18520 
18521 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
18522 
18523 	hdd_exit();
18524 
18525 	return err;
18526 }
18527 
18528 /**
18529  * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
18530  * @wiphy: pointer to wireless wiphy structure.
18531  * @wdev: pointer to wireless_dev structure.
18532  * @data: pointer to apfind configuration data.
18533  * @data_len: the length in byte of apfind data.
18534  *
18535  * This is called when wlan driver needs to send arp stats to
18536  * firmware.
18537  *
18538  * Return: An error code or 0 on success.
18539  */
18540 static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
18541 					   struct wireless_dev *wdev,
18542 					   const void *data, int data_len)
18543 {
18544 	int errno;
18545 	struct osif_vdev_sync *vdev_sync;
18546 
18547 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18548 	if (errno)
18549 		return errno;
18550 
18551 	errno = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
18552 
18553 	osif_vdev_sync_op_stop(vdev_sync);
18554 
18555 	return errno;
18556 }
18557 
18558 #undef STATS_SET_INVALID
18559 #undef STATS_SET_START
18560 #undef STATS_GW_IPV4
18561 #undef STATS_SET_MAX
18562 
18563 /*
18564  * define short names for the global vendor params
18565  * used by wlan_hdd_cfg80211_setarp_stats_cmd()
18566  */
18567 #define STATS_GET_INVALID \
18568 	QCA_ATTR_NUD_STATS_SET_INVALID
18569 #define COUNT_FROM_NETDEV \
18570 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
18571 #define COUNT_TO_LOWER_MAC \
18572 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
18573 #define RX_COUNT_BY_LOWER_MAC \
18574 	QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
18575 #define COUNT_TX_SUCCESS \
18576 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
18577 #define RSP_RX_COUNT_BY_LOWER_MAC \
18578 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
18579 #define RSP_RX_COUNT_BY_UPPER_MAC \
18580 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
18581 #define RSP_COUNT_TO_NETDEV \
18582 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
18583 #define RSP_COUNT_OUT_OF_ORDER_DROP \
18584 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
18585 #define AP_LINK_ACTIVE \
18586 	QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
18587 #define AP_LINK_DAD \
18588 	QCA_ATTR_NUD_STATS_IS_DAD
18589 #define DATA_PKT_STATS \
18590 	QCA_ATTR_NUD_STATS_DATA_PKT_STATS
18591 #define STATS_GET_MAX \
18592 	QCA_ATTR_NUD_STATS_GET_MAX
18593 
18594 #define CHECK_STATS_INVALID \
18595 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
18596 #define CHECK_STATS_PKT_TYPE \
18597 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
18598 #define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
18599 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
18600 #define CHECK_STATS_PKT_SRC_PORT \
18601 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
18602 #define CHECK_STATS_PKT_DEST_PORT \
18603 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
18604 #define CHECK_STATS_PKT_DEST_IPV4 \
18605 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
18606 #define CHECK_STATS_PKT_DEST_IPV6 \
18607 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
18608 #define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
18609 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
18610 #define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
18611 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
18612 #define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
18613 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
18614 #define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
18615 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
18616 #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
18617 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
18618 #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
18619 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
18620 #define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
18621 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
18622 #define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
18623 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
18624 #define CHECK_DATA_STATS_MAX \
18625 	QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
18626 
18627 
18628 const struct nla_policy
18629 qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
18630 	[COUNT_FROM_NETDEV] = {.type = NLA_U16 },
18631 	[COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
18632 	[RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
18633 	[COUNT_TX_SUCCESS] = {.type = NLA_U16 },
18634 	[RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
18635 	[RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
18636 	[RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
18637 	[RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
18638 	[AP_LINK_ACTIVE] = {.type = NLA_FLAG },
18639 	[AP_LINK_DAD] = {.type = NLA_FLAG },
18640 	[DATA_PKT_STATS] = {.type = NLA_U16 },
18641 };
18642 
18643 /**
18644  * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
18645  * @wiphy: pointer to wireless wiphy structure.
18646  * @wdev: pointer to wireless_dev structure.
18647  * @data: pointer to apfind configuration data.
18648  * @data_len: the length in byte of apfind data.
18649  *
18650  * This is called when wlan driver needs to get arp stats to
18651  * firmware.
18652  *
18653  * Return: An error code or 0 on success.
18654  */
18655 static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
18656 					     struct wireless_dev *wdev,
18657 					     const void *data, int data_len)
18658 {
18659 	int err = 0;
18660 	struct net_device *dev = wdev->netdev;
18661 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
18662 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
18663 	struct wlan_objmgr_vdev *vdev;
18664 
18665 	hdd_enter();
18666 
18667 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
18668 		hdd_err("Command not allowed in FTM mode");
18669 		return -EINVAL;
18670 	}
18671 
18672 	err = wlan_hdd_validate_context(hdd_ctx);
18673 	if (0 != err)
18674 		return err;
18675 
18676 	err = hdd_validate_adapter(adapter);
18677 	if (err)
18678 		return err;
18679 
18680 	if (adapter->device_mode != QDF_STA_MODE) {
18681 		hdd_err("STATS supported in only STA mode!");
18682 		return -EINVAL;
18683 	}
18684 
18685 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
18686 	if (!vdev)
18687 		return -EINVAL;
18688 
18689 	err = osif_dp_get_nud_stats(wiphy, vdev, data, data_len);
18690 
18691 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
18692 
18693 	return err;
18694 }
18695 
18696 /**
18697  * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
18698  * @wiphy: pointer to wireless wiphy structure.
18699  * @wdev: pointer to wireless_dev structure.
18700  * @data: pointer to apfind configuration data.
18701  * @data_len: the length in byte of apfind data.
18702  *
18703  * This is called when wlan driver needs to get arp stats to
18704  * firmware.
18705  *
18706  * Return: An error code or 0 on success.
18707  */
18708 static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
18709 					   struct wireless_dev *wdev,
18710 					   const void *data, int data_len)
18711 {
18712 	int errno;
18713 	struct osif_vdev_sync *vdev_sync;
18714 
18715 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
18716 	if (errno)
18717 		return errno;
18718 
18719 	errno = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
18720 
18721 	osif_vdev_sync_op_stop(vdev_sync);
18722 
18723 	return errno;
18724 }
18725 
18726 #undef QCA_ATTR_NUD_STATS_SET_INVALID
18727 #undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
18728 #undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
18729 #undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
18730 #undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
18731 #undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
18732 #undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
18733 #undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
18734 #undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
18735 #undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
18736 #undef QCA_ATTR_NUD_STATS_GET_MAX
18737 
18738 void hdd_bt_activity_cb(hdd_handle_t hdd_handle, uint32_t bt_activity)
18739 {
18740 	struct hdd_context *hdd_ctx = hdd_handle_to_context(hdd_handle);
18741 	int status;
18742 
18743 	status = wlan_hdd_validate_context(hdd_ctx);
18744 	if (0 != status)
18745 		return;
18746 
18747 	if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
18748 		hdd_ctx->bt_a2dp_active = 1;
18749 	else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
18750 		hdd_ctx->bt_a2dp_active = 0;
18751 	else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
18752 		hdd_ctx->bt_vo_active = 1;
18753 	else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
18754 		hdd_ctx->bt_vo_active = 0;
18755 	else if (bt_activity == WLAN_COEX_EVENT_BT_PROFILE_CONNECTED)
18756 		hdd_ctx->bt_profile_con = 1;
18757 	else if (bt_activity == WLAN_COEX_EVENT_BT_PROFILE_DISCONNECTED)
18758 		hdd_ctx->bt_profile_con = 0;
18759 	else
18760 		return;
18761 
18762 	ucfg_scan_set_bt_activity(hdd_ctx->psoc, hdd_ctx->bt_a2dp_active);
18763 	ucfg_mlme_set_bt_profile_con(hdd_ctx->psoc, hdd_ctx->bt_profile_con);
18764 	hdd_debug("a2dp_active: %d vo_active: %d connected:%d",
18765 		  hdd_ctx->bt_a2dp_active,
18766 		  hdd_ctx->bt_vo_active, hdd_ctx->bt_profile_con);
18767 }
18768 
18769 /**
18770  * hdd_post_chain_rssi_rsp - send rsp to user space
18771  * @adapter: Pointer to adapter
18772  * @result: chain rssi result
18773  * @update_chain_rssi: update rssi, if this flag is set
18774  * @update_chain_evm: update evm, if this flag is set
18775  * @update_ant_id: update antenna id, if this flag is set
18776  *
18777  * Return: 0 for success, non-zero for failure
18778  */
18779 static int hdd_post_chain_rssi_rsp(struct hdd_adapter *adapter,
18780 				   struct chain_rssi_result *result,
18781 				   bool update_chain_rssi,
18782 				   bool update_chain_evm,
18783 				   bool update_ant_id)
18784 {
18785 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18786 	struct sk_buff *skb;
18787 	int len = NLMSG_HDRLEN;
18788 
18789 	len += update_chain_rssi ?
18790 		nla_total_size(sizeof(result->chain_rssi)) : 0;
18791 	len += update_chain_evm ?
18792 		nla_total_size(sizeof(result->chain_evm)) : 0;
18793 	len += update_ant_id ?
18794 		nla_total_size(sizeof(result->ant_id)) : 0;
18795 
18796 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, len);
18797 	if (!skb) {
18798 		hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
18799 		return -ENOMEM;
18800 	}
18801 
18802 	if (update_chain_rssi &&
18803 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI,
18804 		    sizeof(result->chain_rssi),
18805 		    result->chain_rssi)) {
18806 		goto nla_put_failure;
18807 	}
18808 
18809 	if (update_chain_evm &&
18810 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_EVM,
18811 		    sizeof(result->chain_evm),
18812 		    result->chain_evm)) {
18813 		goto nla_put_failure;
18814 	}
18815 
18816 	if (update_ant_id &&
18817 	    nla_put(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO,
18818 		    sizeof(result->ant_id),
18819 		    result->ant_id)) {
18820 		goto nla_put_failure;
18821 	}
18822 
18823 	wlan_cfg80211_vendor_cmd_reply(skb);
18824 	return 0;
18825 
18826 nla_put_failure:
18827 	hdd_err("nla put fail");
18828 	wlan_cfg80211_vendor_free_skb(skb);
18829 	return -EINVAL;
18830 }
18831 
18832 #ifdef QCA_SUPPORT_CP_STATS
18833 /**
18834  * hdd_process_peer_chain_rssi_req() - fetch per chain rssi of a connected peer
18835  * @adapter: Pointer to adapter
18836  * @peer_macaddr: mac address of desired peer or AP
18837  *
18838  * Return: 0 for success, non-zero for failure
18839  */
18840 static int hdd_process_peer_chain_rssi_req(struct hdd_adapter *adapter,
18841 					   struct qdf_mac_addr *peer_macaddr)
18842 {
18843 	struct stats_event *stats;
18844 	struct wlan_objmgr_vdev *vdev;
18845 	struct chain_rssi_result chain_rssi;
18846 	int retval, index;
18847 
18848 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
18849 	if (!vdev)
18850 		return -EINVAL;
18851 
18852 	stats = wlan_cfg80211_mc_cp_stats_get_peer_stats(vdev,
18853 							 peer_macaddr->bytes,
18854 							 &retval);
18855 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
18856 
18857 	if (retval || !stats) {
18858 		if (stats)
18859 			wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
18860 		hdd_err("Unable to get chain rssi from fw");
18861 		return retval;
18862 	}
18863 
18864 	for (index = 0; index < WMI_MAX_CHAINS; index++)
18865 		chain_rssi.chain_rssi[index] =
18866 		stats->peer_stats_info_ext->peer_rssi_per_chain[index];
18867 
18868 	wlan_cfg80211_mc_cp_stats_free_stats_event(stats);
18869 
18870 	retval = hdd_post_chain_rssi_rsp(adapter, &chain_rssi,
18871 					 true, false, false);
18872 	if (retval)
18873 		hdd_err("Failed to post chain rssi");
18874 
18875 	return retval;
18876 }
18877 #else
18878 struct chain_rssi_priv {
18879 	struct chain_rssi_result chain_rssi;
18880 };
18881 
18882 /**
18883  * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
18884  * @context: opaque context originally passed to SME. HDD always passes
18885  * a cookie for the request context
18886  * @data: struct for get chain rssi
18887  *
18888  * This function receives the response/data from the lower layer and
18889  * checks to see if the thread is still waiting then post the results to
18890  * upper layer, if the request has timed out then ignore.
18891  *
18892  * Return: None
18893  */
18894 static void hdd_get_chain_rssi_cb(void *context,
18895 				  struct chain_rssi_result *data)
18896 {
18897 	struct osif_request *request;
18898 	struct chain_rssi_priv *priv;
18899 
18900 	hdd_enter();
18901 
18902 	request = osif_request_get(context);
18903 	if (!request) {
18904 		hdd_err("Obsolete request");
18905 		return;
18906 	}
18907 
18908 	priv = osif_request_priv(request);
18909 	priv->chain_rssi = *data;
18910 	osif_request_complete(request);
18911 	osif_request_put(request);
18912 }
18913 
18914 static int hdd_process_peer_chain_rssi_req(struct hdd_adapter *adapter,
18915 					   struct qdf_mac_addr *peer_macaddr)
18916 {
18917 	mac_handle_t mac_handle;
18918 	struct osif_request *request;
18919 	struct chain_rssi_priv *priv;
18920 	struct get_chain_rssi_req_params req_msg;
18921 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18922 	QDF_STATUS status;
18923 	int retval;
18924 	void *cookie;
18925 	static const struct osif_request_params params = {
18926 		.priv_size = sizeof(*priv),
18927 		.timeout_ms = WLAN_WAIT_TIME_STATS,
18928 	};
18929 
18930 	memcpy(&req_msg.peer_macaddr, peer_macaddr->bytes, QDF_MAC_ADDR_SIZE);
18931 	req_msg.session_id = adapter->deflink->vdev_id;
18932 
18933 	request = osif_request_alloc(&params);
18934 	if (!request) {
18935 		hdd_err("Request allocation failure");
18936 		return -ENOMEM;
18937 	}
18938 
18939 	cookie = osif_request_cookie(request);
18940 	mac_handle = hdd_ctx->mac_handle;
18941 	status = sme_get_chain_rssi(mac_handle,
18942 				    &req_msg,
18943 				    hdd_get_chain_rssi_cb,
18944 				    cookie);
18945 
18946 	if (status != QDF_STATUS_SUCCESS) {
18947 		hdd_err("Unable to get chain rssi");
18948 		retval = qdf_status_to_os_return(status);
18949 	} else {
18950 		retval = osif_request_wait_for_response(request);
18951 		if (retval) {
18952 			hdd_err("Target response timed out");
18953 		} else {
18954 			priv = osif_request_priv(request);
18955 			retval = hdd_post_chain_rssi_rsp(adapter,
18956 							 &priv->chain_rssi,
18957 							 true, true, true);
18958 			if (retval)
18959 				hdd_err("Failed to post chain rssi");
18960 		}
18961 	}
18962 	osif_request_put(request);
18963 	return retval;
18964 }
18965 #endif
18966 
18967 static const struct
18968 nla_policy get_chain_rssi_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
18969 	[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]       = {.type = NLA_BINARY,
18970 		.len = QDF_MAC_ADDR_SIZE},
18971 };
18972 
18973 static const struct nla_policy
18974 get_chan_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX + 1] = {
18975 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID] = {.type = NLA_U32},
18976 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ] = {.type = NLA_U32},
18977 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ] = {.type = NLA_U32},
18978 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ] = {.type = NLA_U32},
18979 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH] = {.type = NLA_U32},
18980 	[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK] = {.type = NLA_U32},
18981 };
18982 
18983 static const struct nla_policy
18984 get_usable_channel_policy[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1] = {
18985 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID] = {
18986 		.type = NLA_U32
18987 	},
18988 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK] = {
18989 		.type = NLA_U32
18990 	},
18991 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK] = {
18992 		.type = NLA_U32
18993 	},
18994 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK] = {
18995 		.type = NLA_U32
18996 	},
18997 	[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO] = {
18998 		.type = NLA_NESTED
18999 	},
19000 };
19001 
19002 #ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
19003 static enum nl80211_chan_width
19004 hdd_convert_phy_bw_to_nl_bw(enum phy_ch_width bw)
19005 {
19006 	switch (bw) {
19007 	case CH_WIDTH_20MHZ:
19008 		return NL80211_CHAN_WIDTH_20;
19009 	case CH_WIDTH_40MHZ:
19010 		return NL80211_CHAN_WIDTH_40;
19011 	case CH_WIDTH_160MHZ:
19012 		return NL80211_CHAN_WIDTH_160;
19013 	case CH_WIDTH_80MHZ:
19014 		return NL80211_CHAN_WIDTH_80;
19015 	case CH_WIDTH_80P80MHZ:
19016 		return NL80211_CHAN_WIDTH_80P80;
19017 	case CH_WIDTH_5MHZ:
19018 		return NL80211_CHAN_WIDTH_5;
19019 	case CH_WIDTH_10MHZ:
19020 		return NL80211_CHAN_WIDTH_10;
19021 #if defined(CFG80211_11BE_BASIC)
19022 	case CH_WIDTH_320MHZ:
19023 		return NL80211_CHAN_WIDTH_320;
19024 #else
19025 	case CH_WIDTH_320MHZ:
19026 		return NL80211_CHAN_WIDTH_20;
19027 #endif
19028 	case CH_WIDTH_INVALID:
19029 	case CH_WIDTH_MAX:
19030 		return NL80211_CHAN_WIDTH_20;
19031 	}
19032 
19033 	return NL80211_CHAN_WIDTH_20;
19034 }
19035 
19036 /**
19037  * hdd_fill_usable_channels_data() - Fill the data requested by userspace
19038  * @skb: SK buffer
19039  * @tb: List of attributes
19040  * @res_msg: structure of usable channel info
19041  * @count: no of usable channels
19042  *
19043  * Get the data corresponding to the attribute list specified in tb and
19044  * update the same to skb by populating the same attributes.
19045  *
19046  * Return: 0 on success; error number on failure
19047  */
19048 static int
19049 hdd_fill_usable_channels_data(struct sk_buff *skb, struct nlattr **tb,
19050 			      struct get_usable_chan_res_params *res_msg,
19051 			      int count)
19052 {
19053 	struct nlattr *config, *chan_params;
19054 	uint8_t i, bw, j = 0;
19055 
19056 	config = nla_nest_start(skb,
19057 				QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO);
19058 	if (!config) {
19059 		hdd_err("nla nest start failure");
19060 		return -EINVAL;
19061 	}
19062 	for (i = 0; i < count ; i++) {
19063 		if (!res_msg[i].freq)
19064 			continue;
19065 		chan_params = nla_nest_start(skb, j);
19066 		if (!chan_params)
19067 			return -EINVAL;
19068 		j++;
19069 		bw = hdd_convert_phy_bw_to_nl_bw(res_msg[i].bw);
19070 		if (nla_put_u32(skb,
19071 				QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ,
19072 				res_msg[i].freq) ||
19073 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ,
19074 				res_msg[i].seg0_freq) ||
19075 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ,
19076 				res_msg[i].seg1_freq) ||
19077 		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH,
19078 				bw) ||
19079 		    nla_put_u32(skb,
19080 				QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK,
19081 				res_msg[i].iface_mode_mask)) {
19082 			hdd_err("nla put failure");
19083 			return -EINVAL;
19084 		}
19085 
19086 		nla_nest_end(skb, chan_params);
19087 	}
19088 	nla_nest_end(skb, config);
19089 	return 0;
19090 }
19091 
19092 /**
19093  * hdd_get_usable_channel_len() - calculate the length required by skb
19094  * @count: number of usable channels
19095  *
19096  * Find the required length to send usable channel data to upper layer
19097  *
19098  * Return: required len
19099  */
19100 static uint32_t
19101 hdd_get_usable_channel_len(uint32_t count)
19102 {
19103 	uint32_t len = 0;
19104 	struct get_usable_chan_res_params res_msg;
19105 
19106 	len = nla_total_size(sizeof(res_msg.freq)) +
19107 		nla_total_size(sizeof(res_msg.seg0_freq)) +
19108 		nla_total_size(sizeof(res_msg.seg1_freq)) +
19109 		nla_total_size(sizeof(res_msg.bw)) +
19110 		nla_total_size(sizeof(res_msg.iface_mode_mask));
19111 
19112 	return len * count;
19113 }
19114 
19115 /**
19116  * hdd_send_usable_channel() - Send usable channels as vendor cmd reply
19117  * @hdd_ctx: Pointer to hdd context
19118  * @res_msg: pointer to usable channel information
19119  * @count: number of channels
19120  * @tb: List of attributes
19121  *
19122  * Parse the attributes list tb and  get the data corresponding to the
19123  * attributes specified in tb. Send them as a vendor response.
19124  *
19125  * Return: 0 on success; error number on failure
19126  */
19127 static int
19128 hdd_send_usable_channel(struct hdd_context *hdd_ctx,
19129 			struct get_usable_chan_res_params *res_msg,
19130 			uint32_t count,
19131 			struct nlattr **tb)
19132 {
19133 	struct sk_buff *skb;
19134 	uint32_t skb_len;
19135 	int status;
19136 
19137 	skb_len = hdd_get_usable_channel_len(count);
19138 	if (!skb_len) {
19139 		hdd_err("No data requested");
19140 		return -EINVAL;
19141 	}
19142 
19143 	skb_len += NLMSG_HDRLEN;
19144 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, skb_len);
19145 	if (!skb) {
19146 		hdd_info("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
19147 		return -ENOMEM;
19148 	}
19149 
19150 	status = hdd_fill_usable_channels_data(skb, tb, res_msg, count);
19151 	if (status)
19152 		goto fail;
19153 
19154 	return wlan_cfg80211_vendor_cmd_reply(skb);
19155 
19156 fail:
19157 	hdd_err("nla put fail");
19158 	wlan_cfg80211_vendor_free_skb(skb);
19159 	return status;
19160 }
19161 
19162 /**
19163  * hdd_get_all_band_mask() - get supported nl80211 bands
19164  *
19165  * Return: supported band mask
19166  */
19167 static uint32_t
19168 hdd_get_all_band_mask(void)
19169 {
19170 	uint32_t band_mask = 0;
19171 
19172 	band_mask =
19173 		(1 << REG_BAND_2G) | (1 << REG_BAND_5G) | (1 << REG_BAND_6G);
19174 
19175 	return band_mask;
19176 }
19177 
19178 /**
19179  * hdd_get_all_iface_mode_mask() - get supported nl80211 iface mode
19180  *
19181  * Return: supported iface mode mask
19182  */
19183 static uint32_t
19184 hdd_get_all_iface_mode_mask(void)
19185 {
19186 	uint32_t mode_mask = 0;
19187 
19188 	mode_mask = (1 << NL80211_IFTYPE_STATION) |
19189 			(1 << NL80211_IFTYPE_AP) |
19190 			(1 << NL80211_IFTYPE_P2P_GO) |
19191 			(1 << NL80211_IFTYPE_P2P_CLIENT) |
19192 			(1 << NL80211_IFTYPE_P2P_DEVICE) |
19193 			(1 << NL80211_IFTYPE_NAN);
19194 
19195 	return mode_mask;
19196 }
19197 
19198 /**
19199  * hdd_convert_nl80211_to_reg_band_mask() - convert n80211 band to reg band
19200  * @band: nl80211 band
19201  *
19202  * Return: reg band value
19203  */
19204 
19205 static uint32_t
19206 hdd_convert_nl80211_to_reg_band_mask(enum nl80211_band band)
19207 {
19208 	uint32_t reg_band = 0;
19209 
19210 	if (band & 1 << NL80211_BAND_2GHZ)
19211 		reg_band |= 1 << REG_BAND_2G;
19212 	if (band & 1 << NL80211_BAND_5GHZ)
19213 		reg_band |= 1 << REG_BAND_5G;
19214 	if (band & 1 << NL80211_BAND_6GHZ)
19215 		reg_band |= 1 << REG_BAND_6G;
19216 	if (band & 1 << NL80211_BAND_60GHZ)
19217 		hdd_err("band: %d not supported", NL80211_BAND_60GHZ);
19218 
19219 	return reg_band;
19220 }
19221 
19222 /**
19223  * __wlan_hdd_cfg80211_get_usable_channel() - get chain rssi
19224  * @wiphy: wiphy pointer
19225  * @wdev: pointer to struct wireless_dev
19226  * @data: pointer to incoming NL vendor data
19227  * @data_len: length of @data
19228  *
19229  * Return: 0 on success; error number otherwise.
19230  */
19231 static int __wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
19232 						  struct wireless_dev *wdev,
19233 						  const void *data,
19234 						  int data_len)
19235 {
19236 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19237 	struct get_usable_chan_req_params req_msg = {0};
19238 	struct get_usable_chan_res_params *res_msg;
19239 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1];
19240 	int ret = 0;
19241 	uint32_t count = 0;
19242 	QDF_STATUS status;
19243 
19244 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19245 		hdd_err("Command not allowed in FTM mode");
19246 		return -EPERM;
19247 	}
19248 
19249 	ret = wlan_hdd_validate_context(hdd_ctx);
19250 	if (0 != ret)
19251 		return ret;
19252 
19253 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
19254 		hdd_err("Driver Modules are closed");
19255 		return -EINVAL;
19256 	}
19257 
19258 	res_msg = qdf_mem_malloc(NUM_CHANNELS *
19259 				 sizeof(*res_msg));
19260 
19261 	if (!res_msg) {
19262 		hdd_err("res_msg invalid");
19263 		return -EINVAL;
19264 	}
19265 
19266 	if (wlan_cfg80211_nla_parse(
19267 				tb, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX,
19268 				data, data_len, get_usable_channel_policy)) {
19269 		hdd_err("Invalid ATTR");
19270 		ret = -EINVAL;
19271 		goto err;
19272 	}
19273 
19274 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]) {
19275 		hdd_err("band mask not present");
19276 		req_msg.band_mask = hdd_get_all_band_mask();
19277 	} else {
19278 		req_msg.band_mask =
19279 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]);
19280 		if (!req_msg.band_mask)
19281 			req_msg.band_mask = hdd_get_all_band_mask();
19282 		else
19283 			req_msg.band_mask =
19284 			hdd_convert_nl80211_to_reg_band_mask(req_msg.band_mask);
19285 	}
19286 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]) {
19287 		hdd_err("iface mode mask not present");
19288 		req_msg.iface_mode_mask = hdd_get_all_iface_mode_mask();
19289 	} else {
19290 		req_msg.iface_mode_mask = nla_get_u32(
19291 		tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]);
19292 		if (!req_msg.iface_mode_mask)
19293 			req_msg.iface_mode_mask = hdd_get_all_iface_mode_mask();
19294 	}
19295 
19296 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]) {
19297 		hdd_err("usable channels filter mask not present");
19298 		req_msg.filter_mask = 0;
19299 	} else {
19300 		req_msg.filter_mask =
19301 			nla_get_u32(
19302 			tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]);
19303 	}
19304 
19305 	hdd_debug("get usable channel list for band %d mode %d filter %d",
19306 		  req_msg.band_mask, req_msg.iface_mode_mask,
19307 		  req_msg.filter_mask);
19308 
19309 	status = wlan_reg_get_usable_channel(hdd_ctx->pdev, req_msg,
19310 					     res_msg, &count,
19311 					     REG_CURRENT_PWR_MODE);
19312 	if (QDF_STATUS_SUCCESS != status) {
19313 		hdd_err("get usable channel failed %d", status);
19314 		ret = -EINVAL;
19315 		goto err;
19316 	}
19317 	hdd_debug("usable channel count : %d", count);
19318 
19319 	ret = hdd_send_usable_channel(hdd_ctx, res_msg, count, tb);
19320 	if (ret) {
19321 		hdd_err("failed to send usable_channels");
19322 		ret = -EINVAL;
19323 		goto err;
19324 	}
19325 
19326 err:
19327 	qdf_mem_free(res_msg);
19328 	if (ret)
19329 		return ret;
19330 	return qdf_status_to_os_return(status);
19331 }
19332 #endif
19333 
19334 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
19335 /**
19336  * enum roam_stats_set_params - Different types of params to set the roam stats
19337  * @ROAM_RT_STATS_DISABLED:                Roam stats feature disabled
19338  * @ROAM_RT_STATS_ENABLED:                 Roam stats feature enabled
19339  * @ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE: Roam stats enabled in suspend mode
19340  */
19341 enum roam_stats_set_params {
19342 	ROAM_RT_STATS_DISABLED = 0,
19343 	ROAM_RT_STATS_ENABLED = 1,
19344 	ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE = 2,
19345 };
19346 
19347 #define EVENTS_CONFIGURE QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE
19348 #define SUSPEND_STATE    QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE
19349 
19350 static const struct nla_policy
19351 set_roam_events_policy[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX + 1] = {
19352 	[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE] = {.type = NLA_U8},
19353 	[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE] = {.type = NLA_FLAG},
19354 };
19355 
19356 /**
19357  * __wlan_hdd_cfg80211_set_roam_events() - set roam stats
19358  * @wiphy: wiphy pointer
19359  * @wdev: pointer to struct wireless_dev
19360  * @data: pointer to incoming NL vendor data
19361  * @data_len: length of @data
19362  *
19363  * Return: 0 on success; error number otherwise.
19364  */
19365 static int __wlan_hdd_cfg80211_set_roam_events(struct wiphy *wiphy,
19366 					       struct wireless_dev *wdev,
19367 					       const void *data,
19368 					       int data_len)
19369 {
19370 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19371 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
19372 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX + 1];
19373 	QDF_STATUS status;
19374 	int ret;
19375 	uint8_t config, state, param = 0;
19376 
19377 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19378 		hdd_err("Command not allowed in FTM mode");
19379 		return -EPERM;
19380 	}
19381 
19382 	ret = wlan_hdd_validate_context(hdd_ctx);
19383 	if (ret != 0) {
19384 		hdd_err("Invalid hdd_ctx");
19385 		return ret;
19386 	}
19387 
19388 	ret = hdd_validate_adapter(adapter);
19389 	if (ret != 0) {
19390 		hdd_err("Invalid adapter");
19391 		return ret;
19392 	}
19393 
19394 	if (adapter->device_mode != QDF_STA_MODE) {
19395 		hdd_err("STATS supported in only STA mode!");
19396 		return -EINVAL;
19397 	}
19398 
19399 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX,
19400 				    data, data_len, set_roam_events_policy)) {
19401 		hdd_err("Invalid ATTR");
19402 		return -EINVAL;
19403 	}
19404 
19405 	if (!tb[EVENTS_CONFIGURE]) {
19406 		hdd_err("roam events configure not present");
19407 		return -EINVAL;
19408 	}
19409 
19410 	config = nla_get_u8(tb[EVENTS_CONFIGURE]);
19411 	hdd_debug("roam stats configured: %d", config);
19412 
19413 	if (!tb[SUSPEND_STATE]) {
19414 		hdd_debug("suspend state not present");
19415 		param = config ? ROAM_RT_STATS_ENABLED : ROAM_RT_STATS_DISABLED;
19416 	} else if (config == ROAM_RT_STATS_ENABLED) {
19417 		state = nla_get_flag(tb[SUSPEND_STATE]);
19418 		hdd_debug("Suspend state configured: %d", state);
19419 		param = ROAM_RT_STATS_ENABLED |
19420 			ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE;
19421 	}
19422 
19423 	hdd_debug("roam events param: %d", param);
19424 	ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc,
19425 				     param, ROAM_RT_STATS_ENABLE);
19426 
19427 	if (param == (ROAM_RT_STATS_ENABLED |
19428 		      ROAM_RT_STATS_ENABLED_IN_SUSPEND_MODE)) {
19429 		ucfg_pmo_enable_wakeup_event(hdd_ctx->psoc,
19430 					     adapter->deflink->vdev_id,
19431 					     WOW_ROAM_STATS_EVENT);
19432 		ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc,
19433 					     ROAM_RT_STATS_ENABLED,
19434 					     ROAM_RT_STATS_SUSPEND_MODE_ENABLE);
19435 	} else if (ucfg_cm_get_roam_rt_stats(hdd_ctx->psoc,
19436 					  ROAM_RT_STATS_SUSPEND_MODE_ENABLE)) {
19437 		ucfg_pmo_disable_wakeup_event(hdd_ctx->psoc,
19438 					      adapter->deflink->vdev_id,
19439 					      WOW_ROAM_STATS_EVENT);
19440 		ucfg_cm_update_roam_rt_stats(hdd_ctx->psoc,
19441 					     ROAM_RT_STATS_DISABLED,
19442 					     ROAM_RT_STATS_SUSPEND_MODE_ENABLE);
19443 	}
19444 
19445 	status = ucfg_cm_roam_send_rt_stats_config(hdd_ctx->pdev,
19446 						   adapter->deflink->vdev_id,
19447 						   param);
19448 
19449 	return qdf_status_to_os_return(status);
19450 }
19451 
19452 #undef EVENTS_CONFIGURE
19453 #undef SUSPEND_STATE
19454 
19455 /**
19456  * wlan_hdd_cfg80211_set_roam_events() - set roam stats
19457  * @wiphy: wiphy pointer
19458  * @wdev: pointer to struct wireless_dev
19459  * @data: pointer to incoming NL vendor data
19460  * @data_len: length of @data
19461  *
19462  * Return: 0 on success; error number otherwise.
19463  */
19464 static int wlan_hdd_cfg80211_set_roam_events(struct wiphy *wiphy,
19465 					     struct wireless_dev *wdev,
19466 					     const void *data,
19467 					     int data_len)
19468 {
19469 	int errno;
19470 	struct osif_vdev_sync *vdev_sync;
19471 
19472 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19473 	if (errno)
19474 		return errno;
19475 
19476 	errno = __wlan_hdd_cfg80211_set_roam_events(wiphy, wdev,
19477 						    data, data_len);
19478 
19479 	osif_vdev_sync_op_stop(vdev_sync);
19480 
19481 	return errno;
19482 }
19483 #endif
19484 
19485 /**
19486  * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
19487  * @wiphy: wiphy pointer
19488  * @wdev: pointer to struct wireless_dev
19489  * @data: pointer to incoming NL vendor data
19490  * @data_len: length of @data
19491  *
19492  * Return: 0 on success; error number otherwise.
19493  */
19494 static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
19495 					      struct wireless_dev *wdev,
19496 					      const void *data,
19497 					      int data_len)
19498 {
19499 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
19500 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
19501 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
19502 	struct qdf_mac_addr peer_macaddr;
19503 	int retval;
19504 
19505 	hdd_enter();
19506 
19507 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
19508 		hdd_err("Command not allowed in FTM mode");
19509 		return -EPERM;
19510 	}
19511 
19512 	retval = wlan_hdd_validate_context(hdd_ctx);
19513 	if (0 != retval)
19514 		return retval;
19515 
19516 	if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
19517 				    data, data_len, get_chain_rssi_policy)) {
19518 		hdd_err("Invalid ATTR");
19519 		return -EINVAL;
19520 	}
19521 
19522 	if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
19523 		hdd_err("attr mac addr failed");
19524 		return -EINVAL;
19525 	}
19526 	if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) != QDF_MAC_ADDR_SIZE) {
19527 		hdd_err("incorrect mac size");
19528 		return -EINVAL;
19529 	}
19530 
19531 	qdf_copy_macaddr(&peer_macaddr,
19532 			 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]));
19533 
19534 	retval = hdd_process_peer_chain_rssi_req(adapter, &peer_macaddr);
19535 	hdd_exit();
19536 	return retval;
19537 }
19538 
19539 #ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
19540 /**
19541  * wlan_hdd_cfg80211_get_usable_channel() - get chain rssi
19542  * @wiphy: wiphy pointer
19543  * @wdev: pointer to struct wireless_dev
19544  * @data: pointer to incoming NL vendor data
19545  * @data_len: length of @data
19546  *
19547  * Return: 0 on success; error number otherwise.
19548  */
19549 static int wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
19550 						struct wireless_dev *wdev,
19551 						const void *data,
19552 						int data_len)
19553 {
19554 	int errno;
19555 	struct osif_vdev_sync *vdev_sync;
19556 
19557 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19558 	if (errno)
19559 		return errno;
19560 
19561 	errno = __wlan_hdd_cfg80211_get_usable_channel(wiphy, wdev,
19562 						       data, data_len);
19563 
19564 	osif_vdev_sync_op_stop(vdev_sync);
19565 
19566 	return errno;
19567 }
19568 #else
19569 static int wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
19570 						struct wireless_dev *wdev,
19571 						const void *data,
19572 						int data_len)
19573 {
19574 	hdd_debug("get usable channel feature not supported");
19575 	return -EPERM;
19576 }
19577 #endif
19578 
19579 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
19580 /**
19581  * os_if_monitor_mode_configure() - Wifi monitor mode configuration
19582  * vendor command
19583  * @adapter: hdd adapter
19584  * @data: Vendor command data buffer
19585  * @data_len: Buffer length
19586  *
19587  * Return: QDF_STATUS
19588  */
19589 static
19590 QDF_STATUS os_if_monitor_mode_configure(struct hdd_adapter *adapter,
19591 					const void *data, int data_len)
19592 {
19593 	struct wlan_objmgr_vdev *vdev;
19594 	QDF_STATUS status;
19595 
19596 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
19597 	if (!vdev)
19598 		return QDF_STATUS_E_INVAL;
19599 
19600 	status = os_if_dp_set_lpc_configure(vdev, data, data_len);
19601 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
19602 	return status;
19603 }
19604 
19605 #endif /* WLAN_FEATURE_LOCAL_PKT_CAPTURE */
19606 
19607 #if defined(WLAN_FEATURE_PKT_CAPTURE) || defined(WLAN_FEATURE_LOCAL_PKT_CAPTURE)
19608 
19609 /**
19610  * __wlan_hdd_cfg80211_set_monitor_mode() - Wifi monitor mode configuration
19611  * vendor command
19612  * @wiphy: wiphy device pointer
19613  * @wdev: wireless device pointer
19614  * @data: Vendor command data buffer
19615  * @data_len: Buffer length
19616  *
19617  * Handles .
19618  *
19619  * Return: 0 for Success and negative value for failure
19620  */
19621 static int
19622 __wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy,
19623 				     struct wireless_dev *wdev,
19624 				     const void *data, int data_len)
19625 {
19626 	struct net_device *dev = wdev->netdev;
19627 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19628 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
19629 	int errno;
19630 	QDF_STATUS status;
19631 
19632 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
19633 		hdd_err("Command not allowed in FTM mode");
19634 		return -EPERM;
19635 	}
19636 
19637 	errno = wlan_hdd_validate_context(hdd_ctx);
19638 	if (errno)
19639 		return errno;
19640 
19641 	errno = hdd_validate_adapter(adapter);
19642 	if (errno)
19643 		return errno;
19644 
19645 	if (!(ucfg_pkt_capture_get_mode(hdd_ctx->psoc) ||
19646 	      hdd_is_pkt_capture_mon_enable(adapter) ||
19647 	      ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc)))
19648 		return -EPERM;
19649 
19650 	status = os_if_monitor_mode_configure(adapter, data, data_len);
19651 
19652 	return qdf_status_to_os_return(status);
19653 }
19654 
19655 /**
19656  * wlan_hdd_cfg80211_set_monitor_mode() - set monitor mode
19657  * @wiphy: wiphy pointer
19658  * @wdev: pointer to struct wireless_dev
19659  * @data: pointer to incoming NL vendor data
19660  * @data_len: length of @data
19661  *
19662  * Return: 0 on success; error number otherwise.
19663  */
19664 static int wlan_hdd_cfg80211_set_monitor_mode(struct wiphy *wiphy,
19665 					      struct wireless_dev *wdev,
19666 					      const void *data, int data_len)
19667 {
19668 	int errno;
19669 	struct osif_vdev_sync *vdev_sync;
19670 
19671 	hdd_enter_dev(wdev->netdev);
19672 
19673 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19674 	if (errno)
19675 		return errno;
19676 
19677 	errno = __wlan_hdd_cfg80211_set_monitor_mode(wiphy, wdev,
19678 						     data, data_len);
19679 
19680 	osif_vdev_sync_op_stop(vdev_sync);
19681 
19682 	hdd_exit();
19683 
19684 	return errno;
19685 }
19686 #endif
19687 
19688 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
19689 
19690 /**
19691  * __wlan_hdd_cfg80211_get_monitor_mode() - Get wifi monitor mode configuration
19692  * vendor command
19693  * @wiphy: wiphy device pointer
19694  * @wdev: wireless device pointer
19695  * @data: Vendor command data buffer
19696  * @data_len: Buffer length
19697  *
19698  * Return: 0 for Success and negative value for failure
19699  */
19700 static int
19701 __wlan_hdd_cfg80211_get_monitor_mode(struct wiphy *wiphy,
19702 				     struct wireless_dev *wdev,
19703 				     const void *data, int data_len)
19704 {
19705 	struct net_device *dev = wdev->netdev;
19706 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
19707 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
19708 	struct wlan_objmgr_vdev *vdev;
19709 	int errno;
19710 	QDF_STATUS status;
19711 
19712 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
19713 		hdd_err("Command not allowed in FTM mode");
19714 		return -EPERM;
19715 	}
19716 
19717 	errno = wlan_hdd_validate_context(hdd_ctx);
19718 	if (errno)
19719 		return errno;
19720 
19721 	errno = hdd_validate_adapter(adapter);
19722 	if (errno)
19723 		return errno;
19724 
19725 	if (!ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc))
19726 		return -EPERM;
19727 
19728 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_DP_ID);
19729 	if (!vdev)
19730 		return -EINVAL;
19731 
19732 	status = os_if_dp_get_lpc_state(vdev, data, data_len);
19733 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
19734 
19735 	return qdf_status_to_os_return(status);
19736 }
19737 
19738 /**
19739  * wlan_hdd_cfg80211_get_monitor_mode() - get monitor mode
19740  * @wiphy: wiphy pointer
19741  * @wdev: pointer to struct wireless_dev
19742  * @data: pointer to incoming NL vendor data
19743  * @data_len: length of @data
19744  *
19745  * Return: 0 on success; error number otherwise.
19746  */
19747 static int wlan_hdd_cfg80211_get_monitor_mode(struct wiphy *wiphy,
19748 					      struct wireless_dev *wdev,
19749 					      const void *data, int data_len)
19750 {
19751 	int errno;
19752 	struct osif_vdev_sync *vdev_sync;
19753 
19754 	hdd_enter_dev(wdev->netdev);
19755 
19756 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19757 	if (errno)
19758 		return errno;
19759 
19760 	errno = __wlan_hdd_cfg80211_get_monitor_mode(wiphy, wdev,
19761 						     data, data_len);
19762 
19763 	osif_vdev_sync_op_stop(vdev_sync);
19764 
19765 	hdd_exit();
19766 
19767 	return errno;
19768 }
19769 #endif
19770 
19771 /**
19772  * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
19773  * @wiphy: wiphy pointer
19774  * @wdev: pointer to struct wireless_dev
19775  * @data: pointer to incoming NL vendor data
19776  * @data_len: length of @data
19777  *
19778  * Return: 0 on success; error number otherwise.
19779  */
19780 static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
19781 					    struct wireless_dev *wdev,
19782 					    const void *data,
19783 					    int data_len)
19784 {
19785 	int errno;
19786 	struct osif_vdev_sync *vdev_sync;
19787 
19788 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
19789 	if (errno)
19790 		return errno;
19791 
19792 	errno = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
19793 
19794 	osif_vdev_sync_op_stop(vdev_sync);
19795 
19796 	return errno;
19797 }
19798 
19799 /**
19800  * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
19801  * @skb: Pointer to skb
19802  * @info: mac mode info
19803  * @index: attribute type index for nla_nest_start()
19804  *
19805  * Return : 0 on success and errno on failure
19806  */
19807 static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
19808 				   struct connection_info *info, int index)
19809 {
19810 	struct nlattr *attr;
19811 	uint32_t freq;
19812 	struct hdd_context *hdd_ctx;
19813 	struct wlan_hdd_link_info *link_info;
19814 
19815 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
19816 	if (!hdd_ctx)
19817 		goto error;
19818 
19819 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, info->vdev_id);
19820 	if (!link_info)
19821 		goto error;
19822 
19823 	attr = nla_nest_start(skb, index);
19824 	if (!attr)
19825 		goto error;
19826 
19827 	freq = sme_chn_to_freq(info->channel);
19828 
19829 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
19830 	    link_info->adapter->dev->ifindex) ||
19831 	    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
19832 		goto error;
19833 
19834 	nla_nest_end(skb, attr);
19835 
19836 	return 0;
19837 error:
19838 	hdd_err("Fill buffer with interface info failed");
19839 	return -EINVAL;
19840 }
19841 
19842 /**
19843  * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
19844  * @skb: Pointer to skb
19845  * @info: mac mode info
19846  * @mac_id: MAC id
19847  * @conn_count: number of current connections
19848  *
19849  * Return : 0 on success and errno on failure
19850  */
19851 static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
19852 				  struct connection_info *info, uint32_t mac_id,
19853 				  uint32_t conn_count)
19854 {
19855 	struct nlattr *attr, *intf_attr;
19856 	uint32_t band = 0, i = 0, j = 0;
19857 	bool present = false;
19858 
19859 	while (i < conn_count) {
19860 		if (info[i].mac_id == mac_id) {
19861 			present = true;
19862 			if (info[i].channel <= SIR_11B_CHANNEL_END)
19863 				band |= 1 << NL80211_BAND_2GHZ;
19864 			else if (info[i].channel <= SIR_11A_CHANNEL_END)
19865 				band |= 1 << NL80211_BAND_5GHZ;
19866 		}
19867 		i++;
19868 	}
19869 
19870 	if (!present)
19871 		return 0;
19872 
19873 	i = 0;
19874 	attr = nla_nest_start(skb, mac_id);
19875 	if (!attr)
19876 		goto error;
19877 
19878 	if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
19879 	    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
19880 		goto error;
19881 
19882 	intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
19883 	if (!intf_attr)
19884 		goto error;
19885 
19886 	while (i < conn_count) {
19887 		if (info[i].mac_id == mac_id) {
19888 			if (wlan_hdd_fill_intf_info(skb, &info[i], j))
19889 				return -EINVAL;
19890 			j++;
19891 		}
19892 		i++;
19893 	}
19894 
19895 	nla_nest_end(skb, intf_attr);
19896 
19897 	nla_nest_end(skb, attr);
19898 
19899 	return 0;
19900 error:
19901 	hdd_err("Fill buffer with mac info failed");
19902 	return -EINVAL;
19903 }
19904 
19905 
19906 int wlan_hdd_send_mode_change_event(void)
19907 {
19908 	int err;
19909 	struct hdd_context *hdd_ctx;
19910 	struct sk_buff *skb;
19911 	struct nlattr *attr;
19912 	struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
19913 	uint32_t conn_count, mac_id;
19914 	enum qca_nl80211_vendor_subcmds_index index =
19915 		QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX;
19916 
19917 	hdd_enter();
19918 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
19919 	if (!hdd_ctx)
19920 		return -EINVAL;
19921 
19922 	err = wlan_hdd_validate_context(hdd_ctx);
19923 	if (0 != err)
19924 		return err;
19925 
19926 	conn_count = policy_mgr_get_connection_info(hdd_ctx->psoc, info);
19927 	if (!conn_count)
19928 		return -EINVAL;
19929 
19930 	skb = wlan_cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
19931 					       (sizeof(uint32_t) * 4) *
19932 					       MAX_NUMBER_OF_CONC_CONNECTIONS +
19933 					       NLMSG_HDRLEN,
19934 					       index, GFP_KERNEL);
19935 	if (!skb) {
19936 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
19937 		return -ENOMEM;
19938 	}
19939 
19940 	attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
19941 	if (!attr) {
19942 		hdd_err("nla_nest_start failed");
19943 		wlan_cfg80211_vendor_free_skb(skb);
19944 		return -EINVAL;
19945 	}
19946 
19947 	for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
19948 		if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count)) {
19949 			wlan_cfg80211_vendor_free_skb(skb);
19950 			return -EINVAL;
19951 		}
19952 	}
19953 
19954 	nla_nest_end(skb, attr);
19955 
19956 	wlan_cfg80211_vendor_event(skb, GFP_KERNEL);
19957 	hdd_exit();
19958 
19959 	return err;
19960 }
19961 
19962 
19963 /* Short name for QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS command */
19964 
19965 #define EXTSCAN_CONFIG_MAX \
19966 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX
19967 #define EXTSCAN_CONFIG_REQUEST_ID \
19968 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID
19969 #define EXTSCAN_CONFIG_WIFI_BAND \
19970 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND
19971 #define EXTSCAN_CONFIG_MAX_CHANNELS \
19972 QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS
19973 #define EXTSCAN_RESULTS_NUM_CHANNELS \
19974 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_NUM_CHANNELS
19975 #define EXTSCAN_RESULTS_CHANNELS \
19976 	QCA_WLAN_VENDOR_ATTR_EXTSCAN_RESULTS_CHANNELS
19977 
19978 static const struct nla_policy
19979 wlan_hdd_extscan_get_valid_channels_policy[EXTSCAN_CONFIG_MAX + 1] = {
19980 	[EXTSCAN_CONFIG_REQUEST_ID] = {.type = NLA_U32},
19981 	[EXTSCAN_CONFIG_WIFI_BAND] = {.type = NLA_U32},
19982 	[EXTSCAN_CONFIG_MAX_CHANNELS] = {.type = NLA_U32},
19983 };
19984 
19985 /**
19986  * hdd_remove_passive_channels () - remove passive channels
19987  * @wiphy: Pointer to wireless phy
19988  * @chan_list: channel list
19989  * @num_channels: number of channels
19990  *
19991  * Return: none
19992  */
19993 static void hdd_remove_passive_channels(struct wiphy *wiphy,
19994 					uint32_t *chan_list,
19995 					uint8_t *num_channels)
19996 {
19997 	uint8_t num_chan_temp = 0;
19998 	int i, j, k;
19999 
20000 	for (i = 0; i < *num_channels; i++)
20001 		for (j = 0; j < HDD_NUM_NL80211_BANDS; j++) {
20002 			if (!wiphy->bands[j])
20003 				continue;
20004 			for (k = 0; k < wiphy->bands[j]->n_channels; k++) {
20005 				if ((chan_list[i] ==
20006 				     wiphy->bands[j]->channels[k].center_freq)
20007 				    && (!(wiphy->bands[j]->channels[k].flags &
20008 				       IEEE80211_CHAN_PASSIVE_SCAN))
20009 				) {
20010 					chan_list[num_chan_temp] = chan_list[i];
20011 					num_chan_temp++;
20012 				}
20013 			}
20014 		}
20015 
20016 	*num_channels = num_chan_temp;
20017 }
20018 
20019 /**
20020  * __wlan_hdd_cfg80211_extscan_get_valid_channels () - get valid channels
20021  * @wiphy: Pointer to wireless phy
20022  * @wdev: Pointer to wireless device
20023  * @data: Pointer to data
20024  * @data_len: Data length
20025  *
20026  * Return: none
20027  */
20028 static int
20029 __wlan_hdd_cfg80211_extscan_get_valid_channels(struct wiphy *wiphy,
20030 					       struct wireless_dev
20031 					       *wdev, const void *data,
20032 					       int data_len)
20033 {
20034 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
20035 	struct net_device *dev = wdev->netdev;
20036 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
20037 	uint32_t chan_list[CFG_VALID_CHANNEL_LIST_LEN] = {0};
20038 	uint8_t num_channels  = 0, i, buf[256] = {0};
20039 	struct nlattr *tb[EXTSCAN_CONFIG_MAX + 1];
20040 	uint32_t request_id, max_channels;
20041 	tWifiBand wifi_band;
20042 	QDF_STATUS status;
20043 	struct sk_buff *reply_skb;
20044 	int ret, len = 0;
20045 
20046 	/* ENTER_DEV() intentionally not used in a frequently invoked API */
20047 
20048 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
20049 		hdd_err("Command not allowed in FTM mode");
20050 		return -EPERM;
20051 	}
20052 
20053 	ret = wlan_hdd_validate_context(hdd_ctx);
20054 	if (0 != ret)
20055 		return -EINVAL;
20056 
20057 	if (wlan_cfg80211_nla_parse(tb, EXTSCAN_CONFIG_MAX, data, data_len,
20058 				  wlan_hdd_extscan_get_valid_channels_policy)) {
20059 		hdd_err("Invalid ATTR");
20060 		return -EINVAL;
20061 	}
20062 
20063 	/* Parse and fetch request Id */
20064 	if (!tb[EXTSCAN_CONFIG_REQUEST_ID]) {
20065 		hdd_err("attr request id failed");
20066 		return -EINVAL;
20067 	}
20068 	request_id = nla_get_u32(tb[EXTSCAN_CONFIG_REQUEST_ID]);
20069 
20070 	/* Parse and fetch wifi band */
20071 	if (!tb[EXTSCAN_CONFIG_WIFI_BAND]) {
20072 		hdd_err("attr wifi band failed");
20073 		return -EINVAL;
20074 	}
20075 	wifi_band = nla_get_u32(tb[EXTSCAN_CONFIG_WIFI_BAND]);
20076 	if (!tb[EXTSCAN_CONFIG_MAX_CHANNELS]) {
20077 		hdd_err("attr max channels failed");
20078 		return -EINVAL;
20079 	}
20080 	max_channels = nla_get_u32(tb[EXTSCAN_CONFIG_MAX_CHANNELS]);
20081 
20082 	if (max_channels > CFG_VALID_CHANNEL_LIST_LEN) {
20083 		hdd_err("Max channels %d exceeded Valid channel list len %d",
20084 			max_channels, CFG_VALID_CHANNEL_LIST_LEN);
20085 		return -EINVAL;
20086 	}
20087 
20088 	hdd_err("Req Id: %u Wifi band: %d Max channels: %d", request_id,
20089 		wifi_band, max_channels);
20090 	status = sme_get_valid_channels_by_band(hdd_ctx->mac_handle,
20091 						wifi_band, chan_list,
20092 						&num_channels);
20093 	if (QDF_STATUS_SUCCESS != status) {
20094 		hdd_err("sme_get_valid_channels_by_band failed (err=%d)",
20095 		        status);
20096 		return -EINVAL;
20097 	}
20098 
20099 	num_channels = QDF_MIN(num_channels, max_channels);
20100 
20101 	if ((QDF_SAP_MODE == adapter->device_mode) ||
20102 	    !strncmp(hdd_get_fwpath(), "ap", 2))
20103 		hdd_remove_passive_channels(wiphy, chan_list,
20104 					    &num_channels);
20105 
20106 	hdd_debug("Number of channels: %d", num_channels);
20107 	for (i = 0; i < num_channels; i++)
20108 		len += scnprintf(buf + len, sizeof(buf) - len,
20109 				 "%u ", chan_list[i]);
20110 
20111 	hdd_debug("Channels: %s", buf);
20112 
20113 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
20114 							     sizeof(u32) +
20115 							     sizeof(u32) *
20116 							     num_channels +
20117 							     NLMSG_HDRLEN);
20118 
20119 	if (reply_skb) {
20120 		if (nla_put_u32(
20121 			reply_skb,
20122 			EXTSCAN_RESULTS_NUM_CHANNELS,
20123 			num_channels) ||
20124 		    nla_put(
20125 			reply_skb,
20126 			EXTSCAN_RESULTS_CHANNELS,
20127 			sizeof(u32) * num_channels, chan_list)) {
20128 			hdd_err("nla put fail");
20129 			wlan_cfg80211_vendor_free_skb(reply_skb);
20130 			return -EINVAL;
20131 		}
20132 		ret = wlan_cfg80211_vendor_cmd_reply(reply_skb);
20133 		return ret;
20134 	}
20135 
20136 	hdd_err("valid channels: buffer alloc fail");
20137 	return -EINVAL;
20138 }
20139 
20140 #undef EXTSCAN_CONFIG_MAX
20141 #undef EXTSCAN_CONFIG_REQUEST_ID
20142 #undef EXTSCAN_CONFIG_WIFI_BAND
20143 #undef ETCAN_CONFIG_MAX_CHANNELS
20144 #undef EXTSCAN_RESULTS_NUM_CHANNELS
20145 #undef EXTSCAN_RESULTS_CHANNELS
20146 
20147 /**
20148  * wlan_hdd_cfg80211_extscan_get_valid_channels() - get ext scan valid channels
20149  * @wiphy: Pointer to wireless phy
20150  * @wdev: Pointer to wireless device
20151  * @data: Pointer to data
20152  * @data_len: Data length
20153  *
20154  * Return: 0 on success, negative errno on failure
20155  */
20156 static int wlan_hdd_cfg80211_extscan_get_valid_channels(
20157 					struct wiphy *wiphy,
20158 					struct wireless_dev *wdev,
20159 					const void *data, int data_len)
20160 {
20161 	struct osif_psoc_sync *psoc_sync;
20162 	int errno;
20163 
20164 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
20165 	if (errno)
20166 		return errno;
20167 
20168 	errno = __wlan_hdd_cfg80211_extscan_get_valid_channels(wiphy, wdev,
20169 							       data, data_len);
20170 
20171 	osif_psoc_sync_op_stop(psoc_sync);
20172 
20173 	return errno;
20174 }
20175 
20176 #ifdef FEATURE_RADAR_HISTORY
20177 static uint32_t get_radar_history_evt_len(uint32_t count)
20178 {
20179 	uint32_t data_len = NLMSG_HDRLEN;
20180 
20181 	data_len +=
20182 	/* nested attribute hdr QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES */
20183 		nla_total_size(count *
20184 			       (nla_total_size(
20185 				     /* channel frequency */
20186 				     nla_total_size(sizeof(uint32_t)) +
20187 				     /* timestamp */
20188 				     nla_total_size(sizeof(uint64_t)) +
20189 				     /* radar detected flag */
20190 				     nla_total_size(0))));
20191 
20192 	return data_len;
20193 }
20194 
20195 /**
20196  * __wlan_hdd_cfg80211_get_radar_history () - Get radar history
20197  * @wiphy: Pointer to wireless phy
20198  * @wdev: Pointer to wireless device
20199  * @data: Pointer to data
20200  * @data_len: Data length
20201  *
20202  * Return: 0 on success, negative errno on failure
20203  */
20204 static int
20205 __wlan_hdd_cfg80211_get_radar_history(struct wiphy *wiphy,
20206 				      struct wireless_dev
20207 				      *wdev, const void *data,
20208 				      int data_len)
20209 {
20210 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
20211 	QDF_STATUS status;
20212 	struct sk_buff *reply_skb = NULL;
20213 	int ret, len;
20214 	struct dfs_radar_history *radar_history = NULL;
20215 	uint32_t hist_count = 0;
20216 	int idx;
20217 	struct nlattr *ch_array, *ch_element;
20218 
20219 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
20220 		hdd_err("Command not allowed in FTM mode");
20221 		return -EPERM;
20222 	}
20223 
20224 	ret = wlan_hdd_validate_context(hdd_ctx);
20225 	if (ret)
20226 		return -EINVAL;
20227 
20228 	status = wlansap_query_radar_history(hdd_ctx->mac_handle,
20229 					     &radar_history, &hist_count);
20230 	if (!QDF_IS_STATUS_SUCCESS(status))
20231 		return -EINVAL;
20232 
20233 	len = get_radar_history_evt_len(hist_count);
20234 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
20235 	if (!reply_skb) {
20236 		ret = -ENOMEM;
20237 		goto err;
20238 	}
20239 
20240 	ch_array = nla_nest_start(
20241 			reply_skb, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES);
20242 	if (!ch_array) {
20243 		ret = -ENOMEM;
20244 		goto err;
20245 	}
20246 
20247 	for (idx = 0; idx < hist_count; idx++) {
20248 		ch_element = nla_nest_start(reply_skb, idx);
20249 		if (!ch_element) {
20250 			ret = -ENOMEM;
20251 			goto err;
20252 		}
20253 
20254 		if (nla_put_u32(reply_skb,
20255 				QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ,
20256 				radar_history[idx].ch_freq)) {
20257 			ret = -ENOMEM;
20258 			goto err;
20259 		}
20260 
20261 		if (wlan_cfg80211_nla_put_u64(
20262 			reply_skb,
20263 			QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP,
20264 			radar_history[idx].time)) {
20265 			ret = -ENOMEM;
20266 			goto err;
20267 		}
20268 
20269 		if (radar_history[idx].radar_found &&
20270 		    nla_put_flag(
20271 			reply_skb,
20272 			QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED)) {
20273 			ret = -ENOMEM;
20274 			goto err;
20275 		}
20276 
20277 		nla_nest_end(reply_skb, ch_element);
20278 	}
20279 	nla_nest_end(reply_skb, ch_array);
20280 	qdf_mem_free(radar_history);
20281 
20282 	ret = wlan_cfg80211_vendor_cmd_reply(reply_skb);
20283 	hdd_debug("get radar history count %d, ret %d", hist_count, ret);
20284 
20285 	return ret;
20286 err:
20287 	qdf_mem_free(radar_history);
20288 	wlan_cfg80211_vendor_free_skb(reply_skb);
20289 	hdd_debug("get radar history error %d", ret);
20290 
20291 	return ret;
20292 }
20293 
20294 /**
20295  * wlan_hdd_cfg80211_get_radar_history() - get radar history
20296  * @wiphy: wiphy pointer
20297  * @wdev: pointer to struct wireless_dev
20298  * @data: pointer to incoming NL vendor data
20299  * @data_len: length of @data
20300  *
20301  * Return: 0 on success; error number otherwise.
20302  */
20303 static int wlan_hdd_cfg80211_get_radar_history(struct wiphy *wiphy,
20304 					       struct wireless_dev *wdev,
20305 					       const void *data,
20306 					       int data_len)
20307 {
20308 	int errno;
20309 	struct osif_vdev_sync *vdev_sync;
20310 
20311 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
20312 	if (errno)
20313 		return errno;
20314 
20315 	errno = __wlan_hdd_cfg80211_get_radar_history(wiphy, wdev,
20316 						      data, data_len);
20317 
20318 	osif_vdev_sync_op_stop(vdev_sync);
20319 
20320 	return errno;
20321 }
20322 
20323 #define FEATURE_RADAR_HISTORY_VENDOR_COMMANDS				\
20324 {									\
20325 	.info.vendor_id = QCA_NL80211_VENDOR_ID,			\
20326 	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY,	\
20327 	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |				\
20328 		WIPHY_VENDOR_CMD_NEED_NETDEV |				\
20329 		WIPHY_VENDOR_CMD_NEED_RUNNING,				\
20330 	.doit = wlan_hdd_cfg80211_get_radar_history,			\
20331 	vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)			\
20332 },
20333 #else
20334 #define FEATURE_RADAR_HISTORY_VENDOR_COMMANDS
20335 #endif
20336 
20337 const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
20338 	{
20339 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20340 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
20341 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20342 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20343 		.doit = is_driver_dfs_capable,
20344 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20345 	},
20346 	{
20347 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20348 		.info.subcmd =
20349 			QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
20350 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20351 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20352 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20353 		.doit = wlan_hdd_cfg80211_extscan_get_valid_channels,
20354 		vendor_command_policy(
20355 				wlan_hdd_extscan_get_valid_channels_policy,
20356 				EXTSCAN_PARAM_MAX)
20357 	},
20358 #ifdef WLAN_FEATURE_STATS_EXT
20359 	{
20360 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20361 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
20362 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20363 			 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
20364 		.doit = wlan_hdd_cfg80211_stats_ext_request,
20365 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20366 	},
20367 #endif
20368 
20369 	{
20370 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20371 		.info.subcmd =
20372 			QCA_NL80211_VENDOR_SUBCMD_CONNECTED_CHANNEL_STATS,
20373 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20374 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20375 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20376 		.doit = wlan_hdd_cfg80211_connected_chan_stats_req,
20377 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20378 	},
20379 
20380 	FEATURE_EXTSCAN_VENDOR_COMMANDS
20381 
20382 	FEATURE_LL_STATS_VENDOR_COMMANDS
20383 
20384 	{
20385 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20386 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
20387 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20388 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20389 		.doit = wlan_hdd_cfg80211_get_supported_features,
20390 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20391 	},
20392 	{
20393 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20394 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
20395 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20396 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20397 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20398 		.doit = wlan_hdd_cfg80211_set_scanning_mac_oui,
20399 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20400 	},
20401 
20402 	FEATURE_CONCURRENCY_MATRIX_VENDOR_COMMANDS
20403 
20404 	{
20405 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20406 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
20407 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20408 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20409 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20410 		.doit = wlan_hdd_cfg80211_disable_dfs_chan_scan,
20411 		vendor_command_policy(wlan_hdd_set_no_dfs_flag_config_policy,
20412 				      QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX)
20413 	},
20414 	{
20415 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20416 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
20417 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20418 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20419 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20420 		.doit = wlan_hdd_cfg80211_handle_wisa_cmd,
20421 		vendor_command_policy(wlan_hdd_wisa_cmd_policy,
20422 				      QCA_WLAN_VENDOR_ATTR_WISA_MAX)
20423 	},
20424 
20425 	FEATURE_STATION_INFO_VENDOR_COMMANDS
20426 
20427 	{
20428 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20429 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
20430 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20431 				WIPHY_VENDOR_CMD_NEED_NETDEV |
20432 				WIPHY_VENDOR_CMD_NEED_RUNNING,
20433 		.doit = wlan_hdd_cfg80211_do_acs,
20434 		vendor_command_policy(wlan_hdd_cfg80211_do_acs_policy,
20435 				      QCA_WLAN_VENDOR_ATTR_ACS_MAX)
20436 	},
20437 
20438 	{
20439 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20440 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
20441 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20442 			WIPHY_VENDOR_CMD_NEED_NETDEV,
20443 		.doit = wlan_hdd_cfg80211_get_features,
20444 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20445 	},
20446 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
20447 	{
20448 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20449 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
20450 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20451 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20452 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20453 		.doit = wlan_hdd_cfg80211_keymgmt_set_key,
20454 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20455 	},
20456 #endif
20457 	{
20458 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20459 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
20460 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20461 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20462 		.doit = wlan_hdd_cfg80211_get_wifi_info,
20463 		vendor_command_policy(qca_wlan_vendor_get_wifi_info_policy,
20464 				      QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX)
20465 	},
20466 	{
20467 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20468 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
20469 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20470 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20471 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20472 		.doit = wlan_hdd_cfg80211_wifi_configuration_set,
20473 		vendor_command_policy(wlan_hdd_wifi_config_policy,
20474 				      QCA_WLAN_VENDOR_ATTR_CONFIG_MAX)
20475 	},
20476 	{
20477 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20478 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION,
20479 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20480 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20481 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20482 		.doit = wlan_hdd_cfg80211_wifi_configuration_get,
20483 		vendor_command_policy(wlan_hdd_wifi_config_policy,
20484 				      QCA_WLAN_VENDOR_ATTR_CONFIG_MAX)
20485 	},
20486 
20487 	FEATURE_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION
20488 #ifdef WLAN_SUPPORT_TWT
20489 	FEATURE_VENDOR_SUBCMD_WIFI_CONFIG_TWT
20490 #endif
20491 
20492 	{
20493 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20494 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
20495 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20496 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20497 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20498 		.doit = wlan_hdd_cfg80211_set_ext_roam_params,
20499 		vendor_command_policy(wlan_hdd_set_roam_param_policy,
20500 				      QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX)
20501 	},
20502 	{
20503 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20504 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_RATEMASK_CONFIG,
20505 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20506 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20507 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20508 		.doit = wlan_hdd_cfg80211_set_ratemask_config,
20509 		vendor_command_policy(wlan_hdd_set_ratemask_param_policy,
20510 				      QCA_WLAN_VENDOR_ATTR_RATEMASK_PARAMS_MAX)
20511 	},
20512 	{
20513 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20514 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
20515 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20516 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20517 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20518 		.doit = wlan_hdd_cfg80211_wifi_logger_start,
20519 		vendor_command_policy(
20520 				qca_wlan_vendor_wifi_logger_start_policy,
20521 				QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX)
20522 	},
20523 	{
20524 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20525 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
20526 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV,
20527 		.doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data,
20528 		vendor_command_policy(
20529 			qca_wlan_vendor_wifi_logger_get_ring_data_policy,
20530 			QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX)
20531 	},
20532 	{
20533 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20534 		.info.subcmd =
20535 			QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
20536 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20537 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20538 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20539 		.doit = wlan_hdd_cfg80211_get_preferred_freq_list,
20540 		vendor_command_policy(
20541 			get_preferred_freq_list_policy,
20542 			QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX)
20543 	},
20544 	{
20545 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20546 		.info.subcmd =
20547 			QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
20548 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20549 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20550 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20551 		.doit = wlan_hdd_cfg80211_set_probable_oper_channel,
20552 		vendor_command_policy(
20553 				set_probable_oper_channel_policy,
20554 				QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX)
20555 	},
20556 
20557 	FEATURE_HANDLE_TSF_VENDOR_COMMANDS
20558 
20559 #ifdef FEATURE_WLAN_TDLS
20560 	{
20561 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20562 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
20563 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20564 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20565 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20566 		.doit = wlan_hdd_cfg80211_get_tdls_capabilities,
20567 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20568 	},
20569 #endif
20570 #ifdef WLAN_FEATURE_OFFLOAD_PACKETS
20571 	{
20572 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20573 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
20574 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20575 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20576 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20577 		.doit = wlan_hdd_cfg80211_offloaded_packets,
20578 		vendor_command_policy(offloaded_packet_policy,
20579 				      QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX)
20580 	},
20581 #endif
20582 	FEATURE_RSSI_MONITOR_VENDOR_COMMANDS
20583 	FEATURE_OEM_DATA_VENDOR_COMMANDS
20584 	FEATURE_INTEROP_ISSUES_AP_VENDOR_COMMANDS
20585 
20586 #ifdef WLAN_NS_OFFLOAD
20587 	{
20588 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20589 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
20590 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20591 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20592 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20593 		.doit = wlan_hdd_cfg80211_set_ns_offload,
20594 		vendor_command_policy(ns_offload_set_policy,
20595 				      QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX)
20596 	},
20597 #endif /* WLAN_NS_OFFLOAD */
20598 	{
20599 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20600 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
20601 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20602 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20603 		.doit = wlan_hdd_cfg80211_get_logger_supp_feature,
20604 		vendor_command_policy(get_logger_set_policy,
20605 				      QCA_WLAN_VENDOR_ATTR_LOGGER_MAX)
20606 	},
20607 
20608 	FEATURE_TRIGGER_SCAN_VENDOR_COMMANDS
20609 
20610 	/* Vendor abort scan */
20611 	FEATURE_ABORT_SCAN_VENDOR_COMMANDS
20612 
20613 	/* OCB commands */
20614 	FEATURE_OCB_VENDOR_COMMANDS
20615 
20616 	{
20617 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20618 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
20619 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20620 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20621 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20622 		.doit = wlan_hdd_cfg80211_get_link_properties,
20623 		vendor_command_policy(wlan_hdd_get_link_properties_policy,
20624 				      QCA_WLAN_VENDOR_ATTR_MAX)
20625 	},
20626 
20627 	FEATURE_OTA_TEST_VENDOR_COMMANDS
20628 
20629 	FEATURE_LFR_SUBNET_DETECT_VENDOR_COMMANDS
20630 
20631 	FEATURE_TX_POWER_VENDOR_COMMANDS
20632 
20633 	FEATURE_APF_OFFLOAD_VENDOR_COMMANDS
20634 
20635 	{
20636 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20637 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
20638 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20639 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20640 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20641 		.doit = wlan_hdd_cfg80211_acs_dfs_mode,
20642 		vendor_command_policy(wlan_hdd_set_acs_dfs_config_policy,
20643 				      QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX)
20644 	},
20645 	{
20646 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20647 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
20648 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20649 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20650 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20651 		.doit = wlan_hdd_cfg80211_sta_roam_policy,
20652 		vendor_command_policy(
20653 			wlan_hdd_set_sta_roam_config_policy,
20654 			QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX)
20655 	},
20656 
20657 	{
20658 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20659 		.info.subcmd =
20660 			QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_POLICY,
20661 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20662 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20663 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20664 		.doit = wlan_hdd_cfg80211_concurrent_session_policy,
20665 		vendor_command_policy(
20666 			wlan_hdd_set_concurrent_session_policy,
20667 			QCA_WLAN_VENDOR_ATTR_CONCURRENT_POLICY_MAX)
20668 	},
20669 
20670 #ifdef FEATURE_WLAN_CH_AVOID
20671 	{
20672 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20673 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
20674 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20675 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20676 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20677 		.doit = wlan_hdd_cfg80211_avoid_freq,
20678 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20679 	},
20680 #endif
20681 	{
20682 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20683 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
20684 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20685 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20686 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20687 		.doit = wlan_hdd_cfg80211_sap_configuration_set,
20688 		vendor_command_policy(wlan_hdd_sap_config_policy,
20689 				      QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX)
20690 	},
20691 
20692 	FEATURE_P2P_LISTEN_OFFLOAD_VENDOR_COMMANDS
20693 
20694 	FEATURE_SAP_COND_CHAN_SWITCH_VENDOR_COMMANDS
20695 	{
20696 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20697 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
20698 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20699 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20700 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20701 		.doit = wlan_hdd_cfg80211_get_wakelock_stats,
20702 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20703 	},
20704 	{
20705 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20706 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
20707 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20708 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20709 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20710 		.doit = wlan_hdd_cfg80211_get_bus_size,
20711 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20712 	},
20713 	{
20714 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20715 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
20716 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20717 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20718 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20719 		.doit = wlan_hdd_cfg80211_update_vendor_channel,
20720 		vendor_command_policy(acs_chan_config_policy,
20721 				      QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX)
20722 	},
20723 	{
20724 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20725 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
20726 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20727 					WIPHY_VENDOR_CMD_NEED_NETDEV |
20728 					WIPHY_VENDOR_CMD_NEED_RUNNING,
20729 		.doit = wlan_hdd_cfg80211_setband,
20730 		vendor_command_policy(setband_policy, QCA_WLAN_VENDOR_ATTR_MAX)
20731 	},
20732 	{
20733 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20734 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GETBAND,
20735 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20736 			 WIPHY_VENDOR_CMD_NEED_NETDEV |
20737 			 WIPHY_VENDOR_CMD_NEED_RUNNING,
20738 		.doit = wlan_hdd_cfg80211_getband,
20739 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20740 	},
20741 	{
20742 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20743 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
20744 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20745 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20746 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20747 		.doit = wlan_hdd_cfg80211_set_fast_roaming,
20748 		vendor_command_policy(qca_wlan_vendor_attr,
20749 				      QCA_WLAN_VENDOR_ATTR_MAX)
20750 	},
20751 	FEATURE_DISA_VENDOR_COMMANDS
20752 	FEATURE_TDLS_VENDOR_COMMANDS
20753 	FEATURE_SAR_LIMITS_VENDOR_COMMANDS
20754 	BCN_RECV_FEATURE_VENDOR_COMMANDS
20755 	FEATURE_VENDOR_SUBCMD_SET_TRACE_LEVEL
20756 #ifdef WLAN_FEATURE_LINK_LAYER_STATS
20757 	{
20758 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20759 		.info.subcmd =
20760 			QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
20761 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20762 				 WIPHY_VENDOR_CMD_NEED_NETDEV |
20763 				 WIPHY_VENDOR_CMD_NEED_RUNNING,
20764 		.doit = wlan_hdd_cfg80211_ll_stats_ext_set_param,
20765 		vendor_command_policy(qca_wlan_vendor_ll_ext_policy,
20766 				      QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX)
20767 	},
20768 #endif
20769 	FEATURE_VENDOR_SUBCMD_NUD_STATS_SET
20770 	{
20771 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20772 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
20773 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20774 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20775 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20776 		.doit = wlan_hdd_cfg80211_get_nud_stats,
20777 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20778 	},
20779 
20780 	FEATURE_BSS_TRANSITION_VENDOR_COMMANDS
20781 	FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
20782 	FEATURE_CFR_VENDOR_COMMANDS
20783 	FEATURE_11AX_VENDOR_COMMANDS
20784 
20785 	{
20786 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20787 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
20788 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20789 			WIPHY_VENDOR_CMD_NEED_NETDEV |
20790 			WIPHY_VENDOR_CMD_NEED_RUNNING,
20791 		.doit = wlan_hdd_cfg80211_get_chain_rssi,
20792 		vendor_command_policy(get_chain_rssi_policy,
20793 				      QCA_WLAN_VENDOR_ATTR_MAX)
20794 	},
20795 	{
20796 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20797 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS,
20798 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20799 			WIPHY_VENDOR_CMD_NEED_NETDEV,
20800 		.doit = wlan_hdd_cfg80211_get_usable_channel,
20801 		vendor_command_policy(get_usable_channel_policy,
20802 				      QCA_WLAN_VENDOR_ATTR_MAX)
20803 	},
20804 	FEATURE_ACTIVE_TOS_VENDOR_COMMANDS
20805 	FEATURE_NAN_VENDOR_COMMANDS
20806 	FEATURE_FW_STATE_COMMANDS
20807 	FEATURE_COEX_CONFIG_COMMANDS
20808 	FEATURE_MPTA_HELPER_COMMANDS
20809 	FEATURE_HW_CAPABILITY_COMMANDS
20810 	FEATURE_THERMAL_VENDOR_COMMANDS
20811 	FEATURE_BTC_CHAIN_MODE_COMMANDS
20812 	FEATURE_WMM_COMMANDS
20813 	FEATURE_GPIO_CFG_VENDOR_COMMANDS
20814 	FEATURE_MEDIUM_ASSESS_VENDOR_COMMANDS
20815 	FEATURE_RADAR_HISTORY_VENDOR_COMMANDS
20816 	FEATURE_AVOID_FREQ_EXT_VENDOR_COMMANDS
20817 	FEATURE_MDNS_OFFLOAD_VENDOR_COMMANDS
20818 
20819 	FEATURE_GREEN_AP_LOW_LATENCY_PWR_SAVE_COMMANDS
20820 
20821 #if defined(WLAN_FEATURE_PKT_CAPTURE) || defined(WLAN_FEATURE_LOCAL_PKT_CAPTURE)
20822 	FEATURE_MONITOR_MODE_VENDOR_COMMANDS
20823 #endif
20824 
20825 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
20826 	{
20827 	.info.vendor_id = QCA_NL80211_VENDOR_ID,
20828 	.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS,
20829 	.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20830 		 WIPHY_VENDOR_CMD_NEED_NETDEV |
20831 		 WIPHY_VENDOR_CMD_NEED_RUNNING,
20832 	.doit = wlan_hdd_cfg80211_set_roam_events,
20833 	vendor_command_policy(set_roam_events_policy,
20834 			      QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX)
20835 	},
20836 #endif
20837 	FEATURE_ROAM_STATS_COMMANDS
20838 	FEATURE_WIFI_POS_11AZ_AUTH_COMMANDS
20839 	FEATURE_WIFI_POS_SET_SECURE_RANGING_CONTEXT_COMMANDS
20840 	FEATURE_MCC_QUOTA_VENDOR_COMMANDS
20841 	FEATURE_PEER_FLUSH_VENDOR_COMMANDS
20842 	{
20843 		.info.vendor_id = QCA_NL80211_VENDOR_ID,
20844 		.info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RADIO_COMBINATION_MATRIX,
20845 		.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
20846 			 WIPHY_VENDOR_CMD_NEED_NETDEV,
20847 		.doit = wlan_hdd_cfg80211_get_radio_combination_matrix,
20848 		vendor_command_policy(VENDOR_CMD_RAW_DATA, 0)
20849 	},
20850 	FEATURE_COAP_OFFLOAD_COMMANDS
20851 	FEATURE_ML_LINK_STATE_COMMANDS
20852 	FEATURE_AFC_VENDOR_COMMANDS
20853 	FEATURE_LL_LT_SAP_VENDOR_COMMANDS
20854 	FEATURE_TX_LATENCY_STATS_COMMANDS
20855 };
20856 
20857 struct hdd_context *hdd_cfg80211_wiphy_alloc(void)
20858 {
20859 	struct wiphy *wiphy;
20860 	struct hdd_context *hdd_ctx;
20861 
20862 	hdd_enter();
20863 
20864 	wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, sizeof(*hdd_ctx));
20865 	if (!wiphy) {
20866 		hdd_err("failed to allocate wiphy!");
20867 		return NULL;
20868 	}
20869 
20870 	hdd_ctx = wiphy_priv(wiphy);
20871 	hdd_ctx->wiphy = wiphy;
20872 
20873 	return hdd_ctx;
20874 }
20875 
20876 int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx,
20877 				  struct wiphy *wiphy,
20878 				  enum band_info new_band)
20879 {
20880 	int i, j;
20881 	enum channel_state channel_state;
20882 
20883 	hdd_enter();
20884 
20885 	for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
20886 
20887 		if (!wiphy->bands[i])
20888 			continue;
20889 
20890 		for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
20891 			struct ieee80211_supported_band *band = wiphy->bands[i];
20892 
20893 			channel_state = wlan_reg_get_channel_state_for_pwrmode(
20894 					hdd_ctx->pdev,
20895 					band->channels[j].center_freq,
20896 					REG_CURRENT_PWR_MODE);
20897 
20898 			if (HDD_NL80211_BAND_2GHZ == i &&
20899 			    BAND_5G == new_band) {
20900 				/* 5G only */
20901 #ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
20902 				/* Enable Social channels for P2P */
20903 				if (WLAN_HDD_IS_SOCIAL_CHANNEL
20904 					    (band->channels[j].center_freq)
20905 				    && CHANNEL_STATE_ENABLE ==
20906 				    channel_state)
20907 					band->channels[j].flags &=
20908 						~IEEE80211_CHAN_DISABLED;
20909 				else
20910 #endif
20911 				band->channels[j].flags |=
20912 					IEEE80211_CHAN_DISABLED;
20913 				continue;
20914 			} else if (HDD_NL80211_BAND_5GHZ == i &&
20915 				   BAND_2G == new_band) {
20916 				/* 2G only */
20917 				band->channels[j].flags |=
20918 					IEEE80211_CHAN_DISABLED;
20919 				continue;
20920 			}
20921 
20922 			if (CHANNEL_STATE_DISABLE != channel_state)
20923 				band->channels[j].flags &=
20924 					~IEEE80211_CHAN_DISABLED;
20925 		}
20926 	}
20927 	return 0;
20928 }
20929 
20930 #if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
20931 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
20932 static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
20933 {
20934 	wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
20935 	wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
20936 }
20937 #else
20938 static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
20939 {
20940 }
20941 #endif
20942 
20943 #define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
20944 
20945 #if defined(CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME) || \
20946 		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
20947 /**
20948  * wlan_hdd_cfg80211_action_frame_randomization_init() - Randomize SA of MA
20949  * frames
20950  * @wiphy: Pointer to wiphy
20951  *
20952  * This function is used to indicate the support of source mac address
20953  * randomization of management action frames
20954  *
20955  * Return: None
20956  */
20957 static void
20958 wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
20959 {
20960 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA);
20961 }
20962 #else
20963 static void
20964 wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy)
20965 {
20966 }
20967 #endif
20968 
20969 #if defined(WLAN_FEATURE_FILS_SK) && \
20970 	(defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
20971 		 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
20972 static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
20973 {
20974 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
20975 }
20976 #else
20977 static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
20978 {
20979 }
20980 #endif
20981 
20982 #if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
20983 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
20984 static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
20985 {
20986 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
20987 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
20988 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
20989 }
20990 #else
20991 static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
20992 {
20993 }
20994 #endif
20995 
20996 #if defined(CFG80211_BIGTK_CONFIGURATION_SUPPORT) || \
20997 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
20998 static void wlan_hdd_cfg80211_set_bigtk_flags(struct wiphy *wiphy)
20999 {
21000 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_PROTECTION);
21001 }
21002 #else
21003 static void wlan_hdd_cfg80211_set_bigtk_flags(struct wiphy *wiphy)
21004 {
21005 }
21006 #endif
21007 
21008 #if defined(CFG80211_OCV_CONFIGURATION_SUPPORT) || \
21009 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
21010 static void wlan_hdd_cfg80211_set_ocv_flags(struct wiphy *wiphy)
21011 {
21012 	wiphy_ext_feature_set(wiphy,
21013 			      NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION);
21014 }
21015 #else
21016 static void wlan_hdd_cfg80211_set_ocv_flags(struct wiphy *wiphy)
21017 {
21018 }
21019 #endif
21020 
21021 #if defined(CFG80211_SCAN_OCE_CAPABILITY_SUPPORT) || \
21022 	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
21023 static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
21024 {
21025 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME);
21026 	wiphy_ext_feature_set(wiphy,
21027 			      NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP);
21028 	wiphy_ext_feature_set(wiphy,
21029 			      NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE);
21030 	wiphy_ext_feature_set(
21031 		wiphy, NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION);
21032 }
21033 #else
21034 static void wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(struct wiphy *wiphy)
21035 {
21036 }
21037 #endif
21038 
21039 #if defined(WLAN_FEATURE_SAE) && \
21040 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
21041 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
21042 /**
21043  * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
21044  * @wiphy: Pointer to wiphy
21045  *
21046  * This function is used to indicate the support of SAE
21047  *
21048  * Return: None
21049  */
21050 static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
21051 {
21052 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
21053 
21054 	if (ucfg_fwol_get_sae_enable(hdd_ctx->psoc))
21055 		wiphy->features |= NL80211_FEATURE_SAE;
21056 }
21057 #else
21058 static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy)
21059 {
21060 }
21061 #endif
21062 
21063 #if defined(CFG80211_SAE_AUTH_TA_ADDR_SUPPORT)
21064 static void wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(struct wiphy *wiphy)
21065 {
21066 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_AUTH_TX_RANDOM_TA);
21067 }
21068 #else
21069 static void wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(struct wiphy *wiphy)
21070 {
21071 }
21072 #endif
21073 
21074 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
21075 	defined(CFG80211_DFS_OFFLOAD_BACKPORT)
21076 static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
21077 {
21078 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
21079 }
21080 #else
21081 static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
21082 {
21083 	wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
21084 }
21085 #endif
21086 
21087 #ifdef WLAN_FEATURE_DSRC
21088 static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
21089 					     int *num_ch, int *ch_len)
21090 {
21091 	*num_ch = QDF_ARRAY_SIZE(hdd_channels_dot11p);
21092 	*ch_len = sizeof(hdd_channels_dot11p);
21093 }
21094 
21095 static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
21096 {
21097 	if (!ch_arr_len)
21098 		return;
21099 	qdf_mem_copy(ch_ptr, &hdd_channels_dot11p[0], ch_arr_len);
21100 }
21101 
21102 static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
21103 					    int *num_ch, int *ch_len)
21104 {
21105 	*num_ch = 0;
21106 	*ch_len = 0;
21107 }
21108 
21109 static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
21110 {
21111 }
21112 
21113 /**
21114  * wlan_hdd_populate_5dot9_chan_info() - Populate 5.9 GHz chan info in hdd
21115  * context
21116  * @hdd_ctx: pointer to hdd context
21117  * @index: 5.9 GHz channel beginning index in chan_info of @hdd_ctx
21118  *
21119  * Return: Number of 5.9 GHz channels populated
21120  */
21121 static uint32_t
21122 wlan_hdd_populate_5dot9_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
21123 {
21124 	return 0;
21125 }
21126 
21127 #else
21128 
21129 static void wlan_hdd_get_num_dsrc_ch_and_len(struct hdd_config *hdd_cfg,
21130 					     int *num_ch, int *ch_len)
21131 {
21132 	*num_ch = 0;
21133 	*ch_len = 0;
21134 }
21135 
21136 static void wlan_hdd_copy_dsrc_ch(char *ch_ptr, int ch_arr_len)
21137 {
21138 }
21139 
21140 static void wlan_hdd_get_num_srd_ch_and_len(struct hdd_config *hdd_cfg,
21141 					    int *num_ch, int *ch_len)
21142 {
21143 	*num_ch = QDF_ARRAY_SIZE(hdd_5dot9_ghz_ch);
21144 	*ch_len = sizeof(hdd_5dot9_ghz_ch);
21145 }
21146 
21147 static void wlan_hdd_copy_srd_ch(char *ch_ptr, int ch_arr_len)
21148 {
21149 	if (!ch_arr_len)
21150 		return;
21151 	qdf_mem_copy(ch_ptr, &hdd_5dot9_ghz_ch[0], ch_arr_len);
21152 }
21153 
21154 /**
21155  * wlan_hdd_populate_5dot9_chan_info() - Populate 5.9 GHz chan info in hdd
21156  * context
21157  * @hdd_ctx: pointer to hdd context
21158  * @index: 5.9 GHz channel beginning index in chan_info of @hdd_ctx
21159  *
21160  * Return: Number of 5.9 GHz channels populated
21161  */
21162 static uint32_t
21163 wlan_hdd_populate_5dot9_chan_info(struct hdd_context *hdd_ctx, uint32_t index)
21164 {
21165 	uint32_t num_5dot9_ch, i;
21166 	struct scan_chan_info *chan_info;
21167 
21168 	num_5dot9_ch = QDF_ARRAY_SIZE(hdd_5dot9_ghz_ch);
21169 	chan_info = hdd_ctx->chan_info;
21170 
21171 	for (i = 0; i < num_5dot9_ch; i++)
21172 		chan_info[index + i].freq = hdd_5dot9_ghz_ch[i].center_freq;
21173 
21174 	return num_5dot9_ch;
21175 }
21176 
21177 #endif
21178 
21179 #if defined(WLAN_FEATURE_11AX) && \
21180 	(defined(CFG80211_SBAND_IFTYPE_DATA_BACKPORT) || \
21181 	 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)))
21182 #if defined(CONFIG_BAND_6GHZ) && (defined(CFG80211_6GHZ_BAND_SUPPORTED) || \
21183 	   (KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE))
21184 static QDF_STATUS
21185 wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
21186 {
21187 	hdd_ctx->iftype_data_6g =
21188 			qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_6g) *
21189 				       EHT_OPMODE_SUPPORTED);
21190 
21191 	if (!hdd_ctx->iftype_data_6g)
21192 		return QDF_STATUS_E_NOMEM;
21193 
21194 	return QDF_STATUS_SUCCESS;
21195 }
21196 
21197 static void
21198 wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
21199 {
21200 	qdf_mem_free(hdd_ctx->iftype_data_6g);
21201 	hdd_ctx->iftype_data_6g = NULL;
21202 }
21203 #else
21204 static inline QDF_STATUS
21205 wlan_hdd_iftype_data_alloc_6ghz(struct hdd_context *hdd_ctx)
21206 {
21207 	return QDF_STATUS_SUCCESS;
21208 }
21209 
21210 static inline void
21211 wlan_hdd_iftype_data_mem_free_6ghz(struct hdd_context *hdd_ctx)
21212 {
21213 }
21214 #endif
21215 
21216 static QDF_STATUS
21217 wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
21218 {
21219 	hdd_ctx->iftype_data_2g =
21220 			qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_2g) *
21221 				       EHT_OPMODE_SUPPORTED);
21222 
21223 	if (!hdd_ctx->iftype_data_2g)
21224 		return QDF_STATUS_E_NOMEM;
21225 
21226 	hdd_ctx->iftype_data_5g =
21227 			qdf_mem_malloc(sizeof(*hdd_ctx->iftype_data_5g) *
21228 				       EHT_OPMODE_SUPPORTED);
21229 	if (!hdd_ctx->iftype_data_5g) {
21230 		qdf_mem_free(hdd_ctx->iftype_data_2g);
21231 		hdd_ctx->iftype_data_2g = NULL;
21232 		return QDF_STATUS_E_NOMEM;
21233 	}
21234 
21235 	if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc_6ghz(hdd_ctx))) {
21236 		qdf_mem_free(hdd_ctx->iftype_data_5g);
21237 		qdf_mem_free(hdd_ctx->iftype_data_2g);
21238 		hdd_ctx->iftype_data_2g = NULL;
21239 		hdd_ctx->iftype_data_5g = NULL;
21240 		return QDF_STATUS_E_NOMEM;
21241 	}
21242 
21243 	return QDF_STATUS_SUCCESS;
21244 }
21245 
21246 static void
21247 wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
21248 {
21249 	wlan_hdd_iftype_data_mem_free_6ghz(hdd_ctx);
21250 	qdf_mem_free(hdd_ctx->iftype_data_5g);
21251 	qdf_mem_free(hdd_ctx->iftype_data_2g);
21252 	hdd_ctx->iftype_data_5g = NULL;
21253 	hdd_ctx->iftype_data_2g = NULL;
21254 }
21255 #else
21256 static QDF_STATUS
21257 wlan_hdd_iftype_data_alloc(struct hdd_context *hdd_ctx)
21258 
21259 {
21260 	return QDF_STATUS_SUCCESS;
21261 }
21262 
21263 static inline void
21264 wlan_hdd_iftype_data_mem_free(struct hdd_context *hdd_ctx)
21265 {
21266 }
21267 #endif
21268 
21269 #if defined(WLAN_FEATURE_NAN) && \
21270 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
21271 static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
21272 {
21273 	wiphy->interface_modes |= BIT(NL80211_IFTYPE_NAN);
21274 }
21275 #else
21276 static void wlan_hdd_set_nan_if_mode(struct wiphy *wiphy)
21277 {
21278 }
21279 #endif
21280 
21281 #if defined(WLAN_FEATURE_NAN) && \
21282 	   (KERNEL_VERSION(4, 14, 0) <= LINUX_VERSION_CODE)
21283 static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
21284 {
21285 	wiphy->nan_supported_bands =
21286 		BIT(NL80211_BAND_2GHZ) | BIT(NL80211_BAND_5GHZ);
21287 }
21288 #else
21289 static void wlan_hdd_set_nan_supported_bands(struct wiphy *wiphy)
21290 {
21291 }
21292 #endif
21293 
21294 #if defined(WLAN_FEATURE_NAN) && defined(WLAN_EXT_FEATURE_SECURE_NAN)
21295 /**
21296  * wlan_hdd_set_nan_secure_mode - Populate Secure NAN supported by driver
21297  * @wiphy: wiphy
21298  *
21299  * Return: void
21300  */
21301 static void wlan_hdd_set_nan_secure_mode(struct wiphy *wiphy)
21302 {
21303 	if (sme_is_feature_supported_by_fw(SECURE_NAN))
21304 		wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SECURE_NAN);
21305 }
21306 #else
21307 static void wlan_hdd_set_nan_secure_mode(struct wiphy *wiphy)
21308 {
21309 }
21310 #endif
21311 
21312 /**
21313  * wlan_hdd_update_akm_suit_info() - Populate akm suits supported by driver
21314  * @wiphy: wiphy
21315  *
21316  * Return: void
21317  */
21318 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)) || \
21319 	defined(CFG80211_IFTYPE_AKM_SUITES_SUPPORT)
21320 static void
21321 wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
21322 {
21323 	wiphy->iftype_akm_suites = wlan_hdd_akm_suites;
21324 	wiphy->num_iftype_akm_suites = QDF_ARRAY_SIZE(wlan_hdd_akm_suites);
21325 }
21326 #else
21327 static void
21328 wlan_hdd_update_akm_suit_info(struct wiphy *wiphy)
21329 {
21330 }
21331 #endif
21332 
21333 #ifdef CFG80211_CTRL_FRAME_SRC_ADDR_TA_ADDR
21334 static void wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy *wiphy)
21335 {
21336 	wiphy_ext_feature_set(wiphy,
21337 			      NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211);
21338 	wiphy_ext_feature_set(wiphy,
21339 			      NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH);
21340 }
21341 #else
21342 static void wlan_hdd_update_eapol_over_nl80211_flags(struct wiphy *wiphy)
21343 {
21344 }
21345 #endif
21346 
21347 #ifdef WLAN_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA
21348 /**
21349  * wlan_hdd_set_auth_deauth_random_ta_feature_flag() - set feature flag for
21350  * random address for auth and deauth frames to the kernel.
21351  * @wiphy: wiphy
21352  *
21353  * Return: void
21354  */
21355 static void wlan_hdd_set_auth_deauth_random_ta_feature_flag(struct wiphy *wiphy)
21356 {
21357 	wiphy_ext_feature_set(wiphy,
21358 			      NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA);
21359 }
21360 #else
21361 static void wlan_hdd_set_auth_deauth_random_ta_feature_flag(struct wiphy *wiphy)
21362 {
21363 }
21364 #endif
21365 
21366 #ifdef CFG80211_MULTI_AKM_CONNECT_SUPPORT
21367 static void
21368 wlan_hdd_update_max_connect_akm(struct wiphy *wiphy)
21369 {
21370 	wiphy->max_num_akm_suites = WLAN_CM_MAX_CONNECT_AKMS;
21371 }
21372 #else
21373 static void
21374 wlan_hdd_update_max_connect_akm(struct wiphy *wiphy)
21375 {
21376 }
21377 #endif
21378 
21379 #ifdef NL80211_EXT_FEATURE_PUNCT_SUPPORT
21380 /**
21381  * wlan_hdd_set_ext_feature_punct() - set feature flag for puncture
21382  * @wiphy: wiphy
21383  *
21384  * Return: void
21385  */
21386 static void wlan_hdd_set_ext_feature_punct(struct wiphy *wiphy)
21387 {
21388 	hdd_debug("enable puncture cap");
21389 	wiphy_ext_feature_set(wiphy,
21390 			      NL80211_EXT_FEATURE_PUNCT);
21391 }
21392 #else
21393 static inline void wlan_hdd_set_ext_feature_punct(struct wiphy *wiphy)
21394 {
21395 }
21396 #endif
21397 
21398 /*
21399  * FUNCTION: wlan_hdd_cfg80211_init
21400  * This function is called by hdd_wlan_startup()
21401  * during initialization.
21402  * This function is used to initialize and register wiphy structure.
21403  */
21404 int wlan_hdd_cfg80211_init(struct device *dev,
21405 			   struct wiphy *wiphy, struct hdd_config *config)
21406 {
21407 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
21408 	uint32_t *cipher_suites;
21409 	hdd_enter();
21410 
21411 	/* Now bind the underlying wlan device with wiphy */
21412 	set_wiphy_dev(wiphy, dev);
21413 
21414 	wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
21415 	wlan_hdd_update_akm_suit_info(wiphy);
21416 	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
21417 			| WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
21418 			| WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
21419 #ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
21420 			| WIPHY_FLAG_4ADDR_STATION
21421 #endif
21422 			| WIPHY_FLAG_OFFCHAN_TX
21423 			| WIPHY_FLAG_NETNS_OK;
21424 
21425 	if (ucfg_pmo_get_suspend_mode(hdd_ctx->psoc) == PMO_SUSPEND_WOW) {
21426 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
21427 		wiphy->wowlan = &wowlan_support_cfg80211_init;
21428 #else
21429 		wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
21430 		wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
21431 		wiphy->wowlan.pattern_min_len = 1;
21432 		wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
21433 #endif
21434 	}
21435 
21436 #ifdef FEATURE_WLAN_TDLS
21437 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
21438 			| WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
21439 #endif
21440 
21441 	wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
21442 
21443 	wlan_scan_cfg80211_add_connected_pno_support(wiphy);
21444 
21445 	wiphy->max_scan_ssids = MAX_SCAN_SSID;
21446 
21447 	wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
21448 
21449 	wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
21450 
21451 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
21452 				 | BIT(NL80211_IFTYPE_P2P_CLIENT)
21453 				 | BIT(NL80211_IFTYPE_P2P_GO)
21454 				 | BIT(NL80211_IFTYPE_AP)
21455 				 | BIT(NL80211_IFTYPE_MONITOR);
21456 
21457 	wlan_hdd_set_nan_if_mode(wiphy);
21458 
21459 	/*
21460 	 * In case of static linked driver at the time of driver unload,
21461 	 * module exit doesn't happens. Module cleanup helps in cleaning
21462 	 * of static memory.
21463 	 * If driver load happens statically, at the time of driver unload,
21464 	 * wiphy flags don't get reset because of static memory.
21465 	 * It's better not to store channel in static memory.
21466 	 * The memory is for channels of struct wiphy and shouldn't be
21467 	 * released during stop modules. So if it's allocated in active
21468 	 * domain, the memory leak detector would catch the leak during
21469 	 * stop modules. To avoid this,alloc in init domain in advance.
21470 	 */
21471 	hdd_ctx->channels_2ghz = qdf_mem_malloc(band_2_ghz_channels_size);
21472 	if (!hdd_ctx->channels_2ghz)
21473 		return -ENOMEM;
21474 
21475 	hdd_ctx->channels_5ghz = qdf_mem_malloc(band_5_ghz_channels_size);
21476 	if (!hdd_ctx->channels_5ghz)
21477 		goto mem_fail_5g;
21478 
21479 	if (QDF_IS_STATUS_ERROR(wlan_hdd_iftype_data_alloc(hdd_ctx)))
21480 		goto mem_fail_iftype_data;
21481 
21482 	/*Initialise the supported cipher suite details */
21483 	if (ucfg_fwol_get_gcmp_enable(hdd_ctx->psoc)) {
21484 		cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
21485 					       sizeof(hdd_gcmp_cipher_suits));
21486 		if (!cipher_suites)
21487 			goto mem_fail_cipher_suites;
21488 		wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
21489 			 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
21490 		qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
21491 			     sizeof(hdd_cipher_suites));
21492 		qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
21493 			     &hdd_gcmp_cipher_suits,
21494 			     sizeof(hdd_gcmp_cipher_suits));
21495 	} else {
21496 		cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
21497 		if (!cipher_suites)
21498 			goto mem_fail_cipher_suites;
21499 		wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
21500 		qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
21501 			     sizeof(hdd_cipher_suites));
21502 	}
21503 	wiphy->cipher_suites = cipher_suites;
21504 	cipher_suites = NULL;
21505 	/*signal strength in mBm (100*dBm) */
21506 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
21507 	wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
21508 
21509 	wiphy->n_vendor_commands = ARRAY_SIZE(hdd_wiphy_vendor_commands);
21510 	wiphy->vendor_commands = hdd_wiphy_vendor_commands;
21511 
21512 	wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
21513 	wiphy->n_vendor_events = ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
21514 
21515 #ifdef QCA_HT_2040_COEX
21516 	wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
21517 #endif
21518 	wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
21519 
21520 	wiphy->features |= NL80211_FEATURE_VIF_TXPOWER;
21521 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
21522 	defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
21523 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
21524 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
21525 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
21526 #endif
21527 
21528 	hdd_add_channel_switch_support(&wiphy->flags);
21529 	wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
21530 
21531 	wlan_hdd_update_max_connect_akm(wiphy);
21532 
21533 	wlan_hdd_cfg80211_action_frame_randomization_init(wiphy);
21534 	wlan_hdd_cfg8011_sae_auth_tx_randoam_ta(wiphy);
21535 
21536 	wlan_hdd_set_nan_supported_bands(wiphy);
21537 
21538 	wlan_hdd_update_eapol_over_nl80211_flags(wiphy);
21539 
21540 	wlan_hdd_set_auth_deauth_random_ta_feature_flag(wiphy);
21541 	wlan_hdd_set_ext_feature_punct(wiphy);
21542 
21543 	hdd_exit();
21544 	return 0;
21545 
21546 mem_fail_cipher_suites:
21547 	wlan_hdd_iftype_data_mem_free(hdd_ctx);
21548 mem_fail_iftype_data:
21549 	qdf_mem_free(hdd_ctx->channels_5ghz);
21550 	hdd_ctx->channels_5ghz = NULL;
21551 mem_fail_5g:
21552 	hdd_err("Not enough memory to allocate channels");
21553 	qdf_mem_free(hdd_ctx->channels_2ghz);
21554 	hdd_ctx->channels_2ghz = NULL;
21555 
21556 	return -ENOMEM;
21557 }
21558 
21559 /**
21560  * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
21561  * @wiphy: the wiphy to validate against
21562  *
21563  * this function deinit cfg80211 and cleanup the
21564  * memory allocated in wlan_hdd_cfg80211_init also
21565  * reset the global reg params.
21566  *
21567  * Return: void
21568  */
21569 void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
21570 {
21571 	int i;
21572 	const uint32_t *cipher_suites;
21573 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
21574 
21575 	for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
21576 		if (wiphy->bands[i] &&
21577 		   (wiphy->bands[i]->channels))
21578 			wiphy->bands[i]->channels = NULL;
21579 	}
21580 	wlan_hdd_iftype_data_mem_free(hdd_ctx);
21581 	qdf_mem_free(hdd_ctx->channels_5ghz);
21582 	qdf_mem_free(hdd_ctx->channels_2ghz);
21583 	hdd_ctx->channels_2ghz = NULL;
21584 	hdd_ctx->channels_5ghz = NULL;
21585 
21586 	cipher_suites = wiphy->cipher_suites;
21587 	wiphy->cipher_suites = NULL;
21588 	wiphy->n_cipher_suites = 0;
21589 	qdf_mem_free((uint32_t *)cipher_suites);
21590 	cipher_suites = NULL;
21591 	hdd_reset_global_reg_params();
21592 }
21593 
21594 /**
21595  * wlan_hdd_update_ht_cap() - update HT capabilities for supported bands
21596  * @hdd_ctx: HDD context
21597  *
21598  * this function will update HT capabilities for supported bands
21599  *
21600  * Return: void
21601  */
21602 static void wlan_hdd_update_ht_cap(struct hdd_context *hdd_ctx)
21603 {
21604 	struct mlme_ht_capabilities_info ht_cap_info = {0};
21605 	QDF_STATUS status;
21606 	uint32_t channel_bonding_mode;
21607 	struct ieee80211_supported_band *band_2g;
21608 	struct ieee80211_supported_band *band_5g;
21609 	uint8_t i;
21610 
21611 	status = ucfg_mlme_get_ht_cap_info(hdd_ctx->psoc, &ht_cap_info);
21612 	if (QDF_STATUS_SUCCESS != status)
21613 		hdd_err("could not get HT capability info");
21614 
21615 	band_2g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ];
21616 	band_5g = hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ];
21617 
21618 	if (band_2g) {
21619 		if (ht_cap_info.tx_stbc)
21620 			band_2g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
21621 
21622 		if (!sme_is_feature_supported_by_fw(DOT11AC)) {
21623 			band_2g->vht_cap.vht_supported = 0;
21624 			band_2g->vht_cap.cap = 0;
21625 		}
21626 
21627 		if (!ht_cap_info.short_gi_20_mhz)
21628 			band_2g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
21629 
21630 		for (i = 0; i < hdd_ctx->num_rf_chains; i++)
21631 			band_2g->ht_cap.mcs.rx_mask[i] = 0xff;
21632 
21633 		/*
21634 		 * According to mcs_nss HT MCS parameters highest data rate for
21635 		 * Nss = 1 is 150 Mbps
21636 		 */
21637 		band_2g->ht_cap.mcs.rx_highest =
21638 				cpu_to_le16(150 * hdd_ctx->num_rf_chains);
21639 	}
21640 
21641 	if (band_5g) {
21642 		if (ht_cap_info.tx_stbc)
21643 			band_5g->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
21644 
21645 		if (!sme_is_feature_supported_by_fw(DOT11AC)) {
21646 			band_5g->vht_cap.vht_supported = 0;
21647 			band_5g->vht_cap.cap = 0;
21648 		}
21649 
21650 		if (!ht_cap_info.short_gi_20_mhz)
21651 			band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
21652 
21653 		if (!ht_cap_info.short_gi_40_mhz)
21654 			band_5g->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
21655 
21656 		ucfg_mlme_get_channel_bonding_5ghz(hdd_ctx->psoc,
21657 						   &channel_bonding_mode);
21658 		if (!channel_bonding_mode)
21659 			band_5g->ht_cap.cap &=
21660 					~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
21661 
21662 		for (i = 0; i < hdd_ctx->num_rf_chains; i++)
21663 			band_5g->ht_cap.mcs.rx_mask[i] = 0xff;
21664 		/*
21665 		 * According to mcs_nss HT MCS parameters highest data rate for
21666 		 * Nss = 1 is 150 Mbps
21667 		 */
21668 		band_5g->ht_cap.mcs.rx_highest =
21669 				cpu_to_le16(150 * hdd_ctx->num_rf_chains);
21670 	}
21671 }
21672 
21673 /**
21674  * wlan_hdd_update_band_cap_in_wiphy() - update channel flags based on band cap
21675  * @hdd_ctx: HDD context
21676  *
21677  * This function updates the channel flags based on the band capability set
21678  * in the MLME CFG
21679  *
21680  * Return: void
21681  */
21682 static void wlan_hdd_update_band_cap_in_wiphy(struct hdd_context *hdd_ctx)
21683 {
21684 	int i, j;
21685 	uint32_t band_capability;
21686 	QDF_STATUS status;
21687 	struct ieee80211_supported_band *band;
21688 
21689 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_capability);
21690 	if (QDF_IS_STATUS_ERROR(status)) {
21691 		hdd_err("Failed to get MLME Band Capability");
21692 		return;
21693 	}
21694 
21695 	for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
21696 		if (!hdd_ctx->wiphy->bands[i])
21697 			continue;
21698 
21699 		for (j = 0; j < hdd_ctx->wiphy->bands[i]->n_channels; j++) {
21700 			band = hdd_ctx->wiphy->bands[i];
21701 
21702 			if (HDD_NL80211_BAND_2GHZ == i &&
21703 			    BIT(REG_BAND_5G) == band_capability) {
21704 				/* 5G only */
21705 #ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
21706 				/* Enable social channels for P2P */
21707 				if (WLAN_HDD_IS_SOCIAL_CHANNEL
21708 				    (band->channels[j].center_freq))
21709 					band->channels[j].flags &=
21710 						~IEEE80211_CHAN_DISABLED;
21711 				else
21712 #endif
21713 				band->channels[j].flags |=
21714 					IEEE80211_CHAN_DISABLED;
21715 				continue;
21716 			} else if (HDD_NL80211_BAND_5GHZ == i &&
21717 				   BIT(REG_BAND_2G) == band_capability) {
21718 				/* 2G only */
21719 				band->channels[j].flags |=
21720 					IEEE80211_CHAN_DISABLED;
21721 				continue;
21722 			}
21723 		}
21724 	}
21725 }
21726 
21727 #ifdef FEATURE_WLAN_ESE
21728 /**
21729  * wlan_hdd_update_lfr_wiphy() - update LFR flag based on configures
21730  * @hdd_ctx: HDD context
21731  *
21732  * This function updates the LFR flag based on LFR configures
21733  *
21734  * Return: void
21735  */
21736 static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
21737 {
21738 	bool fast_transition_enabled;
21739 	bool lfr_enabled;
21740 	bool ese_enabled;
21741 	bool roam_offload;
21742 
21743 	ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
21744 					     &fast_transition_enabled);
21745 	ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
21746 	ucfg_mlme_is_ese_enabled(hdd_ctx->psoc, &ese_enabled);
21747 	ucfg_mlme_get_roaming_offload(hdd_ctx->psoc, &roam_offload);
21748 	if (fast_transition_enabled || lfr_enabled || ese_enabled ||
21749 	    roam_offload)
21750 		hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
21751 }
21752 #else
21753 static void wlan_hdd_update_lfr_wiphy(struct hdd_context *hdd_ctx)
21754 {
21755 	bool fast_transition_enabled;
21756 	bool lfr_enabled;
21757 	bool roam_offload;
21758 
21759 	ucfg_mlme_is_fast_transition_enabled(hdd_ctx->psoc,
21760 					     &fast_transition_enabled);
21761 	ucfg_mlme_is_lfr_enabled(hdd_ctx->psoc, &lfr_enabled);
21762 	ucfg_mlme_get_roaming_offload(hdd_ctx->psoc, &roam_offload);
21763 	if (fast_transition_enabled || lfr_enabled || roam_offload)
21764 		hdd_ctx->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
21765 }
21766 #endif
21767 
21768 #if defined (CFG80211_SA_QUERY_OFFLOAD_SUPPORT) || \
21769 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0))
21770 /**
21771  * wlan_hdd_set_sa_query_offload_wiphy() - set sa query offload cap in sme cap
21772  * @hdd_ctx: HDD context
21773  *
21774  * This function set sa query offload cap for ap sme capabilities in wiphy
21775  *
21776  * Return: void
21777  */
21778 static void wlan_hdd_set_sa_query_offload_wiphy(struct hdd_context *hdd_ctx)
21779 {
21780 	hdd_ctx->wiphy->ap_sme_capa |= NL80211_AP_SME_SA_QUERY_OFFLOAD;
21781 }
21782 
21783 /**
21784  * wlan_hdd_update_ap_sme_cap_wiphy() - update ap sme capabilities in wiphy
21785  * @hdd_ctx: HDD context
21786  *
21787  * This function update ap sme capabilities in wiphy
21788  *
21789  * Return: void
21790  */
21791 static void wlan_hdd_update_ap_sme_cap_wiphy(struct hdd_context *hdd_ctx)
21792 {
21793 	wlan_hdd_set_sa_query_offload_wiphy(hdd_ctx);
21794 }
21795 #else
21796 static void wlan_hdd_update_ap_sme_cap_wiphy(struct hdd_context *hdd_ctx)
21797 {
21798 }
21799 #endif
21800 
21801 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
21802 static inline
21803 void wlan_hdd_set_mlo_wiphy_ext_feature(struct wiphy *wiphy,
21804 					struct hdd_context *hdd_ctx)
21805 {
21806 	bool eht_capab;
21807 
21808 	wlan_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
21809 	if (!eht_capab)
21810 		return;
21811 
21812 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
21813 }
21814 #else
21815 static inline
21816 void wlan_hdd_set_mlo_wiphy_ext_feature(struct wiphy *wiphy,
21817 					struct hdd_context *hdd_ctx)
21818 {
21819 }
21820 #endif
21821 
21822 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
21823 static inline
21824 void wlan_hdd_set_ext_kek_kck_support(struct wiphy *wiphy)
21825 {
21826 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK;
21827 }
21828 #else
21829 static inline
21830 void wlan_hdd_set_ext_kek_kck_support(struct wiphy *wiphy)
21831 {
21832 }
21833 #endif
21834 
21835 #ifdef NL80211_KCK_EXT_LEN_32
21836 static inline
21837 void wlan_hdd_set_32bytes_kck_support(struct wiphy *wiphy)
21838 {
21839 	wiphy->flags |= WIPHY_FLAG_SUPPORTS_EXT_KCK_32;
21840 }
21841 #else
21842 static inline
21843 void wlan_hdd_set_32bytes_kck_support(struct wiphy *wiphy)
21844 {
21845 }
21846 #endif
21847 
21848 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
21849 static void wlan_hdd_set_vlan_offload(struct hdd_context *hdd_ctx)
21850 {
21851 	if (ucfg_mlme_is_multipass_sap(hdd_ctx->psoc))
21852 		wiphy_ext_feature_set(hdd_ctx->wiphy,
21853 				      NL80211_EXT_FEATURE_VLAN_OFFLOAD);
21854 }
21855 #else
21856 static void wlan_hdd_set_vlan_offload(struct hdd_context *hdd_ctx)
21857 {
21858 }
21859 #endif
21860 
21861 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
21862 static void wlan_hdd_set_mfp_optional(struct wiphy *wiphy)
21863 {
21864 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MFP_OPTIONAL);
21865 }
21866 #else
21867 static void wlan_hdd_set_mfp_optional(struct wiphy *wiphy)
21868 {
21869 }
21870 #endif
21871 
21872 /**
21873  * wlan_hdd_iface_debug_string() - This API converts IFACE type to string
21874  * @iface_type: interface type
21875  *
21876  * Return: name string
21877  */
21878 static char *wlan_hdd_iface_debug_string(uint32_t iface_type)
21879 {
21880 	if (iface_type == BIT(NL80211_IFTYPE_STATION))
21881 		return "STA";
21882 	else if (iface_type == BIT(NL80211_IFTYPE_AP))
21883 		return "SAP";
21884 	else if (iface_type == (BIT(NL80211_IFTYPE_P2P_CLIENT) |
21885 		 BIT(NL80211_IFTYPE_P2P_GO)))
21886 		return "(P2P_CLI or P2P_GO)";
21887 	else if (iface_type == BIT(NL80211_IFTYPE_P2P_CLIENT))
21888 		return "P2P_CLIENT";
21889 	else if (iface_type == BIT(NL80211_IFTYPE_P2P_GO))
21890 		return "P2P_GO";
21891 	else if (iface_type == BIT(NL80211_IFTYPE_NAN))
21892 		return "NAN";
21893 	else if (iface_type == BIT(NL80211_IFTYPE_MONITOR))
21894 		return "MONITOR";
21895 
21896 	return "invalid iface";
21897 }
21898 
21899 #define IFACE_DUMP_SIZE 100
21900 /**
21901  * wlan_hdd_dump_iface_combinations() - This API prints the IFACE combinations
21902  * @num: number of combinations
21903  * @combination: pointer to iface combination structure
21904  *
21905  * Return: void
21906  */
21907 static void wlan_hdd_dump_iface_combinations(uint32_t num,
21908 			const struct ieee80211_iface_combination *combination)
21909 {
21910 	int i, j;
21911 	char buf[IFACE_DUMP_SIZE] = {0};
21912 	uint8_t len = 0;
21913 
21914 	hdd_debug("max combinations %d", num);
21915 
21916 	for (i = 0; i < num; i++) {
21917 		for (j = 0; j < combination[i].max_interfaces; j++) {
21918 			if (combination[i].limits[j].types)
21919 				len += qdf_scnprintf(buf + len,
21920 						     IFACE_DUMP_SIZE - len,
21921 						     " + %s",
21922 					wlan_hdd_iface_debug_string(
21923 					combination[i].limits[j].types));
21924 		}
21925 
21926 		hdd_nofl_debug("iface combination[%d]: %s", i, buf);
21927 		len = 0;
21928 	}
21929 }
21930 
21931 /*
21932  * In this function, wiphy structure is updated after QDF
21933  * initialization. In wlan_hdd_cfg80211_init, only the
21934  * default values will be initialized. The final initialization
21935  * of all required members can be done here.
21936  */
21937 void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
21938 {
21939 	int value = 0;
21940 	bool fils_enabled, mac_spoofing_enabled;
21941 	bool dfs_master_capable = true, is_oce_sta_enabled = false;
21942 	QDF_STATUS status;
21943 	struct wiphy *wiphy = hdd_ctx->wiphy;
21944 	uint8_t allow_mcc_go_diff_bi = 0, enable_mcc = 0;
21945 	bool is_bigtk_supported;
21946 	bool is_ocv_supported;
21947 	uint8_t iface_num;
21948 
21949 	if (!wiphy) {
21950 		hdd_err("Invalid wiphy");
21951 		return;
21952 	}
21953 	ucfg_mlme_get_sap_max_peers(hdd_ctx->psoc, &value);
21954 	hdd_ctx->wiphy->max_ap_assoc_sta = value;
21955 	wlan_hdd_update_ht_cap(hdd_ctx);
21956 	wlan_hdd_update_band_cap_in_wiphy(hdd_ctx);
21957 	wlan_hdd_update_lfr_wiphy(hdd_ctx);
21958 	wlan_hdd_update_ap_sme_cap_wiphy(hdd_ctx);
21959 
21960 	fils_enabled = 0;
21961 	status = ucfg_mlme_get_fils_enabled_info(hdd_ctx->psoc,
21962 						 &fils_enabled);
21963 	if (QDF_IS_STATUS_ERROR(status))
21964 		hdd_err("could not get fils enabled info");
21965 	if (fils_enabled)
21966 		wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy);
21967 
21968 	status = ucfg_mlme_get_dfs_master_capability(hdd_ctx->psoc,
21969 						     &dfs_master_capable);
21970 	if (QDF_IS_STATUS_SUCCESS(status) && dfs_master_capable)
21971 		wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy);
21972 
21973 
21974 	status = ucfg_mlme_get_bigtk_support(hdd_ctx->psoc,
21975 					     &is_bigtk_supported);
21976 
21977 	if (QDF_IS_STATUS_SUCCESS(status) && is_bigtk_supported)
21978 		wlan_hdd_cfg80211_set_bigtk_flags(wiphy);
21979 
21980 	status = ucfg_mlme_get_ocv_support(hdd_ctx->psoc,
21981 					   &is_ocv_supported);
21982 	if (QDF_IS_STATUS_SUCCESS(status) && is_ocv_supported)
21983 		wlan_hdd_cfg80211_set_ocv_flags(wiphy);
21984 
21985 	status = ucfg_mlme_get_oce_sta_enabled_info(hdd_ctx->psoc,
21986 						    &is_oce_sta_enabled);
21987 	if (QDF_IS_STATUS_ERROR(status))
21988 		hdd_err("could not get OCE STA enable info");
21989 	if (is_oce_sta_enabled)
21990 		wlan_hdd_cfg80211_set_wiphy_oce_scan_flags(wiphy);
21991 
21992 	wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy);
21993 
21994 	if (QDF_STATUS_SUCCESS !=
21995 	    ucfg_policy_mgr_get_allow_mcc_go_diff_bi(hdd_ctx->psoc,
21996 						     &allow_mcc_go_diff_bi))
21997 		hdd_err("can't get mcc_go_diff_bi value, use default");
21998 
21999 	if (QDF_STATUS_SUCCESS !=
22000 	    ucfg_mlme_get_mcc_feature(hdd_ctx->psoc, &enable_mcc))
22001 		hdd_err("can't get enable_mcc value, use default");
22002 
22003 	if (hdd_ctx->config->advertise_concurrent_operation) {
22004 		if (enable_mcc) {
22005 			int i;
22006 
22007 			for (i = 0;
22008 			     i < ARRAY_SIZE(wlan_hdd_iface_combination);
22009 			     i++) {
22010 				if (!allow_mcc_go_diff_bi)
22011 					wlan_hdd_iface_combination[i].
22012 					beacon_int_infra_match = true;
22013 			}
22014 		}
22015 
22016 		if (!ucfg_policy_mgr_is_fw_supports_dbs(hdd_ctx->psoc)) {
22017 			wiphy->iface_combinations =
22018 						wlan_hdd_derived_combination;
22019 			iface_num = ARRAY_SIZE(wlan_hdd_derived_combination);
22020 		} else {
22021 			wiphy->iface_combinations = wlan_hdd_iface_combination;
22022 			iface_num = ARRAY_SIZE(wlan_hdd_iface_combination);
22023 		}
22024 
22025 		wiphy->n_iface_combinations = iface_num;
22026 
22027 		wlan_hdd_dump_iface_combinations(wiphy->n_iface_combinations,
22028 						 wiphy->iface_combinations);
22029 	}
22030 
22031 	mac_spoofing_enabled = ucfg_scan_is_mac_spoofing_enabled(hdd_ctx->psoc);
22032 	if (mac_spoofing_enabled)
22033 		wlan_hdd_cfg80211_scan_randomization_init(wiphy);
22034 
22035 	wlan_wifi_pos_cfg80211_set_wiphy_ext_feature(wiphy, hdd_ctx->psoc);
22036 	wlan_hdd_set_mlo_wiphy_ext_feature(wiphy, hdd_ctx);
22037 	wlan_hdd_set_ext_kek_kck_support(wiphy);
22038 	wlan_hdd_set_32bytes_kck_support(wiphy);
22039 	wlan_hdd_set_nan_secure_mode(wiphy);
22040 	wlan_hdd_set_vlan_offload(hdd_ctx);
22041 	wlan_hdd_set_mfp_optional(wiphy);
22042 }
22043 
22044 /**
22045  * wlan_hdd_update_11n_mode - update 11n mode
22046  * @hdd_ctx: hdd ccontext
22047  *
22048  * this function updated 11n mode in hdd cfg and UMAC
22049  *
22050  * Return: void
22051  */
22052 void wlan_hdd_update_11n_mode(struct hdd_context *hdd_ctx)
22053 {
22054 	struct hdd_config *cfg = hdd_ctx->config;
22055 
22056 	if (sme_is_feature_supported_by_fw(DOT11AC)) {
22057 		hdd_debug("support 11ac");
22058 	} else {
22059 		hdd_debug("not support 11ac");
22060 		if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
22061 		    (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
22062 			cfg->dot11Mode = eHDD_DOT11_MODE_11n;
22063 			ucfg_mlme_set_sap_11ac_override(hdd_ctx->psoc, 0);
22064 			ucfg_mlme_set_go_11ac_override(hdd_ctx->psoc, 0);
22065 		}
22066 	}
22067 }
22068 
22069 QDF_STATUS wlan_hdd_update_wiphy_supported_band(struct hdd_context *hdd_ctx)
22070 {
22071 	int len_5g_ch, num_ch;
22072 	int num_dsrc_ch, len_dsrc_ch, num_srd_ch, len_srd_ch;
22073 	bool is_vht_for_24ghz = false;
22074 	QDF_STATUS status;
22075 	struct hdd_config *cfg = hdd_ctx->config;
22076 	struct wiphy *wiphy = hdd_ctx->wiphy;
22077 
22078 	if (wiphy->registered)
22079 		return QDF_STATUS_SUCCESS;
22080 
22081 	if (hdd_is_2g_supported(hdd_ctx)) {
22082 		if (!hdd_ctx->channels_2ghz)
22083 			return QDF_STATUS_E_NOMEM;
22084 		wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
22085 		wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
22086 							hdd_ctx->channels_2ghz;
22087 		qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
22088 			     &hdd_channels_2_4_ghz[0],
22089 			     sizeof(hdd_channels_2_4_ghz));
22090 
22091 		status = ucfg_mlme_get_vht_for_24ghz(hdd_ctx->psoc,
22092 						     &is_vht_for_24ghz);
22093 		if (QDF_IS_STATUS_ERROR(status))
22094 			hdd_err("could not get VHT capability");
22095 
22096 		if (is_vht_for_24ghz &&
22097 		    sme_is_feature_supported_by_fw(DOT11AC) &&
22098 		    (cfg->dot11Mode == eHDD_DOT11_MODE_AUTO ||
22099 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY ||
22100 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ac ||
22101 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ax ||
22102 		     cfg->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY))
22103 			wlan_hdd_band_2_4_ghz.vht_cap.vht_supported = 1;
22104 	}
22105 	if (!hdd_is_5g_supported(hdd_ctx) ||
22106 	    (eHDD_DOT11_MODE_11b == cfg->dot11Mode) ||
22107 	    (eHDD_DOT11_MODE_11g == cfg->dot11Mode) ||
22108 	    (eHDD_DOT11_MODE_11b_ONLY == cfg->dot11Mode) ||
22109 	    (eHDD_DOT11_MODE_11g_ONLY == cfg->dot11Mode))
22110 		return QDF_STATUS_SUCCESS;
22111 
22112 	if (!hdd_ctx->channels_5ghz)
22113 		return QDF_STATUS_E_NOMEM;
22114 	wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
22115 	wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels = hdd_ctx->channels_5ghz;
22116 	wlan_hdd_get_num_dsrc_ch_and_len(cfg, &num_dsrc_ch, &len_dsrc_ch);
22117 	wlan_hdd_get_num_srd_ch_and_len(cfg, &num_srd_ch, &len_srd_ch);
22118 	num_ch = QDF_ARRAY_SIZE(hdd_channels_5_ghz) + num_dsrc_ch + num_srd_ch;
22119 	len_5g_ch = sizeof(hdd_channels_5_ghz);
22120 
22121 	wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels = num_ch;
22122 	qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels,
22123 		     &hdd_channels_5_ghz[0], len_5g_ch);
22124 	if (num_dsrc_ch)
22125 		wlan_hdd_copy_dsrc_ch((char *)wiphy->bands[
22126 				      HDD_NL80211_BAND_5GHZ]->channels +
22127 				      len_5g_ch, len_dsrc_ch);
22128 	if (num_srd_ch)
22129 		wlan_hdd_copy_srd_ch((char *)wiphy->bands[
22130 				     HDD_NL80211_BAND_5GHZ]->channels +
22131 				     len_5g_ch, len_srd_ch);
22132 
22133 	if (cfg->dot11Mode != eHDD_DOT11_MODE_AUTO &&
22134 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ac &&
22135 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ac_ONLY &&
22136 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ax &&
22137 	    cfg->dot11Mode != eHDD_DOT11_MODE_11ax_ONLY)
22138 		 wlan_hdd_band_5_ghz.vht_cap.vht_supported = 0;
22139 
22140 	if (cfg->dot11Mode == eHDD_DOT11_MODE_AUTO ||
22141 	    cfg->dot11Mode == eHDD_DOT11_MODE_11ax ||
22142 	    cfg->dot11Mode == eHDD_DOT11_MODE_11ax_ONLY)
22143 		hdd_init_6ghz(hdd_ctx);
22144 
22145 	return QDF_STATUS_SUCCESS;
22146 }
22147 
22148 /* In this function we are registering wiphy. */
22149 int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
22150 {
22151 	int ret;
22152 
22153 	hdd_enter();
22154 	ret = wiphy_register(wiphy);
22155 	/* Register our wiphy dev with cfg80211 */
22156 	if (ret < 0) {
22157 		hdd_err("wiphy register failed %d", ret);
22158 		return -EIO;
22159 	}
22160 
22161 	hdd_exit();
22162 	return 0;
22163 }
22164 
22165 /* This function registers for all frame which supplicant is interested in */
22166 int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
22167 {
22168 	mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
22169 	/* Register for all P2P action, public action etc frames */
22170 	uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
22171 	QDF_STATUS status = QDF_STATUS_E_INVAL;
22172 
22173 	hdd_enter();
22174 	if (adapter->device_mode == QDF_FTM_MODE) {
22175 		hdd_info("No need to register frames in FTM mode");
22176 		return 0;
22177 	}
22178 
22179 	if (!mac_handle) {
22180 		hdd_err("mac_handle is NULL, failed to register frames");
22181 		goto ret_status;
22182 	}
22183 
22184 	/* Register frame indication call back */
22185 	status = sme_register_mgmt_frame_ind_callback(mac_handle,
22186 						      hdd_indicate_mgmt_frame);
22187 	if (status != QDF_STATUS_SUCCESS) {
22188 		hdd_err("Failed to register hdd_indicate_mgmt_frame");
22189 		goto ret_status;
22190 	}
22191 
22192 	/* Right now we are registering these frame when driver is getting
22193 	 * initialized. Once we will move to 2.6.37 kernel, in which we have
22194 	 * frame register ops, we will move this code as a part of that
22195 	 */
22196 
22197 	/* GAS Initial Request */
22198 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22199 					 (uint8_t *) GAS_INITIAL_REQ,
22200 					 GAS_INITIAL_REQ_SIZE);
22201 	if (status != QDF_STATUS_SUCCESS) {
22202 		hdd_err("Failed to register GAS_INITIAL_REQ");
22203 		goto ret_status;
22204 	}
22205 
22206 	/* GAS Initial Response */
22207 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22208 					 (uint8_t *) GAS_INITIAL_RSP,
22209 					 GAS_INITIAL_RSP_SIZE);
22210 	if (status != QDF_STATUS_SUCCESS) {
22211 		hdd_err("Failed to register GAS_INITIAL_RSP");
22212 		goto dereg_gas_initial_req;
22213 	}
22214 
22215 	/* GAS Comeback Request */
22216 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22217 					 (uint8_t *) GAS_COMEBACK_REQ,
22218 					 GAS_COMEBACK_REQ_SIZE);
22219 	if (status != QDF_STATUS_SUCCESS) {
22220 		hdd_err("Failed to register GAS_COMEBACK_REQ");
22221 		goto dereg_gas_initial_rsp;
22222 	}
22223 
22224 	/* GAS Comeback Response */
22225 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22226 					 (uint8_t *) GAS_COMEBACK_RSP,
22227 					 GAS_COMEBACK_RSP_SIZE);
22228 	if (status != QDF_STATUS_SUCCESS) {
22229 		hdd_err("Failed to register GAS_COMEBACK_RSP");
22230 		goto dereg_gas_comeback_req;
22231 	}
22232 
22233 	/* WNM BSS Transition Request frame */
22234 	status = sme_register_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22235 					 (uint8_t *) WNM_BSS_ACTION_FRAME,
22236 					 WNM_BSS_ACTION_FRAME_SIZE);
22237 	if (status != QDF_STATUS_SUCCESS) {
22238 		hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
22239 		goto dereg_gas_comeback_rsp;
22240 	}
22241 
22242 	/* WNM-Notification */
22243 	status = sme_register_mgmt_frame(mac_handle,
22244 					 adapter->deflink->vdev_id, type,
22245 					 (uint8_t *) WNM_NOTIFICATION_FRAME,
22246 					 WNM_NOTIFICATION_FRAME_SIZE);
22247 	if (status != QDF_STATUS_SUCCESS) {
22248 		hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
22249 		goto dereg_wnm_bss_action_frm;
22250 	}
22251 
22252 	return 0;
22253 
22254 dereg_wnm_bss_action_frm:
22255 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22256 				  (uint8_t *) WNM_BSS_ACTION_FRAME,
22257 				  WNM_BSS_ACTION_FRAME_SIZE);
22258 dereg_gas_comeback_rsp:
22259 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22260 				  (uint8_t *) GAS_COMEBACK_RSP,
22261 				  GAS_COMEBACK_RSP_SIZE);
22262 dereg_gas_comeback_req:
22263 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22264 				  (uint8_t *) GAS_COMEBACK_REQ,
22265 				  GAS_COMEBACK_REQ_SIZE);
22266 dereg_gas_initial_rsp:
22267 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22268 				  (uint8_t *) GAS_INITIAL_RSP,
22269 				  GAS_INITIAL_RSP_SIZE);
22270 dereg_gas_initial_req:
22271 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22272 				  (uint8_t *) GAS_INITIAL_REQ,
22273 				  GAS_INITIAL_REQ_SIZE);
22274 ret_status:
22275 	return qdf_status_to_os_return(status);
22276 }
22277 
22278 void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
22279 {
22280 	mac_handle_t mac_handle = hdd_adapter_get_mac_handle(adapter);
22281 	/* Deregister for all P2P action, public action etc frames */
22282 	uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
22283 
22284 	hdd_enter();
22285 
22286 	if (!mac_handle) {
22287 		hdd_err("mac_handle is NULL, failed to deregister frames");
22288 		return;
22289 	}
22290 
22291 	/* Right now we are registering these frame when driver is getting
22292 	 * initialized. Once we will move to 2.6.37 kernel, in which we have
22293 	 * frame register ops, we will move this code as a part of that
22294 	 */
22295 
22296 	/* GAS Initial Request */
22297 
22298 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22299 				  (uint8_t *) GAS_INITIAL_REQ,
22300 				  GAS_INITIAL_REQ_SIZE);
22301 
22302 	/* GAS Initial Response */
22303 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22304 				  (uint8_t *) GAS_INITIAL_RSP,
22305 				  GAS_INITIAL_RSP_SIZE);
22306 
22307 	/* GAS Comeback Request */
22308 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22309 				  (uint8_t *) GAS_COMEBACK_REQ,
22310 				  GAS_COMEBACK_REQ_SIZE);
22311 
22312 	/* GAS Comeback Response */
22313 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22314 				  (uint8_t *) GAS_COMEBACK_RSP,
22315 				  GAS_COMEBACK_RSP_SIZE);
22316 
22317 	/* P2P Public Action */
22318 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22319 				  (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
22320 				  P2P_PUBLIC_ACTION_FRAME_SIZE);
22321 
22322 	/* P2P Action */
22323 	sme_deregister_mgmt_frame(mac_handle, SME_SESSION_ID_ANY, type,
22324 				  (uint8_t *) P2P_ACTION_FRAME,
22325 				  P2P_ACTION_FRAME_SIZE);
22326 
22327 	/* WNM-Notification */
22328 	sme_deregister_mgmt_frame(mac_handle, adapter->deflink->vdev_id, type,
22329 				  (uint8_t *) WNM_NOTIFICATION_FRAME,
22330 				  WNM_NOTIFICATION_FRAME_SIZE);
22331 }
22332 
22333 bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
22334 {
22335 	const uint8_t *vendor_ie;
22336 
22337 	if (length < 2) {
22338 		hdd_debug("bss size is less than expected");
22339 		return true;
22340 	}
22341 	if (!ies) {
22342 		hdd_debug("invalid IE pointer");
22343 		return true;
22344 	}
22345 	vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
22346 				VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
22347 	if (vendor_ie) {
22348 		hdd_debug("AP can't support immediate powersave. defer it");
22349 		return false;
22350 	}
22351 	return true;
22352 }
22353 
22354 QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_context *hdd_ctx,
22355 					       uint32_t ch_freq)
22356 {
22357 	bool value = 0;
22358 	uint32_t i;
22359 	struct regulatory_channel *cur_chan_list;
22360 	QDF_STATUS status;
22361 
22362 	status = ucfg_mlme_get_sap_allow_all_channels(hdd_ctx->psoc, &value);
22363 	if (status != QDF_STATUS_SUCCESS)
22364 		hdd_err("Unable to fetch sap allow all channels");
22365 	status = QDF_STATUS_E_INVAL;
22366 	if (value) {
22367 		/* Validate the channel */
22368 		for (i = CHAN_ENUM_2412; i < NUM_CHANNELS; i++) {
22369 			if (ch_freq == WLAN_REG_CH_TO_FREQ(i)) {
22370 				status = QDF_STATUS_SUCCESS;
22371 				break;
22372 			}
22373 		}
22374 	} else {
22375 		cur_chan_list = qdf_mem_malloc(NUM_CHANNELS *
22376 				sizeof(struct regulatory_channel));
22377 		if (!cur_chan_list)
22378 			return QDF_STATUS_E_NOMEM;
22379 
22380 		if (wlan_reg_get_secondary_current_chan_list(
22381 		    hdd_ctx->pdev, cur_chan_list) != QDF_STATUS_SUCCESS) {
22382 			qdf_mem_free(cur_chan_list);
22383 			return QDF_STATUS_E_INVAL;
22384 		}
22385 
22386 		for (i = 0; i < NUM_CHANNELS; i++) {
22387 			if (ch_freq != cur_chan_list[i].center_freq)
22388 				continue;
22389 			if (cur_chan_list[i].state != CHANNEL_STATE_DISABLE &&
22390 			    cur_chan_list[i].state != CHANNEL_STATE_INVALID)
22391 				status = QDF_STATUS_SUCCESS;
22392 			break;
22393 		}
22394 		qdf_mem_free(cur_chan_list);
22395 	}
22396 
22397 	return status;
22398 
22399 }
22400 
22401 static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
22402 					  struct net_device *dev,
22403 					  struct bss_parameters *params)
22404 {
22405 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22406 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22407 	struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
22408 	int ret = 0;
22409 	QDF_STATUS qdf_ret_status;
22410 	mac_handle_t mac_handle;
22411 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
22412 	cdp_config_param_type vdev_param;
22413 
22414 	hdd_enter();
22415 
22416 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
22417 		hdd_err("Command not allowed in FTM mode");
22418 		return -EINVAL;
22419 	}
22420 
22421 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
22422 		return -EINVAL;
22423 
22424 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22425 		   TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
22426 		   adapter->deflink->vdev_id, params->ap_isolate);
22427 
22428 	hdd_debug("Device_mode %s(%d), ap_isolate = %d",
22429 		  qdf_opmode_str(adapter->device_mode),
22430 		  adapter->device_mode, params->ap_isolate);
22431 
22432 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22433 	ret = wlan_hdd_validate_context(hdd_ctx);
22434 	if (0 != ret)
22435 		return ret;
22436 
22437 	if (!(adapter->device_mode == QDF_SAP_MODE ||
22438 	      adapter->device_mode == QDF_P2P_GO_MODE)) {
22439 		return -EOPNOTSUPP;
22440 	}
22441 
22442 	/* ap_isolate == -1 means that in change bss, upper layer doesn't
22443 	 * want to update this parameter
22444 	 */
22445 	if (-1 != params->ap_isolate) {
22446 		ap_ctx->disable_intrabss_fwd = !!params->ap_isolate;
22447 
22448 		mac_handle = hdd_ctx->mac_handle;
22449 		qdf_ret_status = sme_ap_disable_intra_bss_fwd(
22450 						mac_handle,
22451 						adapter->deflink->vdev_id,
22452 						ap_ctx->disable_intrabss_fwd);
22453 		if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
22454 			ret = -EINVAL;
22455 
22456 		ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->pdev,
22457 					 adapter->deflink->vdev_id,
22458 					 ap_ctx->disable_intrabss_fwd);
22459 
22460 		vdev_param.cdp_vdev_param_ap_brdg_en =
22461 			!ap_ctx->disable_intrabss_fwd;
22462 		cdp_txrx_set_vdev_param(soc, adapter->deflink->vdev_id,
22463 					CDP_ENABLE_AP_BRIDGE, vdev_param);
22464 	}
22465 
22466 	hdd_exit();
22467 	return ret;
22468 }
22469 
22470 /**
22471  * hdd_change_adapter_mode() - change @adapter's operating mode to @new_mode
22472  * @adapter: the adapter to change modes on
22473  * @new_mode: the new operating mode to change to
22474  *
22475  * Return: Errno
22476  */
22477 static int hdd_change_adapter_mode(struct hdd_adapter *adapter,
22478 				   enum QDF_OPMODE new_mode)
22479 {
22480 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22481 	struct net_device *netdev = adapter->dev;
22482 	QDF_STATUS status = QDF_STATUS_SUCCESS;
22483 
22484 	hdd_enter();
22485 
22486 	hdd_stop_adapter(hdd_ctx, adapter);
22487 	hdd_deinit_adapter(hdd_ctx, adapter, true);
22488 	adapter->device_mode = new_mode;
22489 	memset(&adapter->deflink->session, 0,
22490 	       sizeof(adapter->deflink->session));
22491 	hdd_set_station_ops(netdev);
22492 
22493 	hdd_exit();
22494 
22495 	return qdf_status_to_os_return(status);
22496 }
22497 
22498 static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
22499 					struct net_device *dev,
22500 					struct bss_parameters *params)
22501 {
22502 	int errno;
22503 	struct osif_vdev_sync *vdev_sync;
22504 
22505 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
22506 	if (errno)
22507 		return errno;
22508 
22509 	errno = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
22510 
22511 	osif_vdev_sync_op_stop(vdev_sync);
22512 
22513 	return errno;
22514 }
22515 
22516 static bool hdd_is_client_mode(enum QDF_OPMODE mode)
22517 {
22518 	switch (mode) {
22519 	case QDF_STA_MODE:
22520 	case QDF_P2P_CLIENT_MODE:
22521 	case QDF_P2P_DEVICE_MODE:
22522 		return true;
22523 	default:
22524 		return false;
22525 	}
22526 }
22527 
22528 static bool hdd_is_ap_mode(enum QDF_OPMODE mode)
22529 {
22530 	switch (mode) {
22531 	case QDF_SAP_MODE:
22532 	case QDF_P2P_GO_MODE:
22533 		return true;
22534 	default:
22535 		return false;
22536 	}
22537 }
22538 
22539 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
22540 	!defined(WLAN_HDD_MULTI_VDEV_SINGLE_NDEV)
22541 static QDF_STATUS
22542 hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter)
22543 {
22544 	int i;
22545 	QDF_STATUS status;
22546 	struct hdd_adapter *link_adapter;
22547 	struct hdd_mlo_adapter_info *mlo_adapter_info;
22548 	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
22549 	struct qdf_mac_addr link_addr[WLAN_MAX_ML_BSS_LINKS] = {0};
22550 
22551 	status = hdd_derive_link_address_from_mld(hdd_ctx->psoc,
22552 						  &adapter->mld_addr,
22553 						  &link_addr[0],
22554 						  WLAN_MAX_ML_BSS_LINKS);
22555 	if (QDF_IS_STATUS_ERROR(status))
22556 		return status;
22557 
22558 	mlo_adapter_info = &adapter->mlo_adapter_info;
22559 	for (i = 0; i < WLAN_MAX_MLD; i++) {
22560 		link_adapter = mlo_adapter_info->link_adapter[i];
22561 		qdf_copy_macaddr(&adapter->link_info[i].link_addr,
22562 				 &link_addr[i]);
22563 		if (!link_adapter)
22564 			continue;
22565 
22566 		ucfg_dp_update_intf_mac(hdd_ctx->psoc, &link_adapter->mac_addr,
22567 					&link_addr[i],
22568 					link_adapter->deflink->vdev);
22569 		qdf_copy_macaddr(&link_adapter->mac_addr, &link_addr[i]);
22570 	}
22571 	qdf_copy_macaddr(&adapter->link_info[i].link_addr, &link_addr[i]);
22572 
22573 	return QDF_STATUS_SUCCESS;
22574 }
22575 #else
22576 static inline QDF_STATUS
22577 hdd_adapter_update_mac_on_mode_change(struct hdd_adapter *adapter)
22578 {
22579 	return QDF_STATUS_SUCCESS;
22580 }
22581 #endif
22582 
22583 /**
22584  * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
22585  * @wiphy: Pointer to the wiphy structure
22586  * @ndev: Pointer to the net device
22587  * @type: Interface type
22588  * @flags: Flags for change interface
22589  * @params: Pointer to change interface parameters
22590  *
22591  * Return: 0 for success, error number on failure.
22592  */
22593 static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
22594 					    struct net_device *ndev,
22595 					    enum nl80211_iftype type,
22596 					    u32 *flags,
22597 					    struct vif_params *params)
22598 {
22599 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
22600 	struct hdd_context *hdd_ctx;
22601 	bool iff_up = ndev->flags & IFF_UP;
22602 	enum QDF_OPMODE new_mode;
22603 	bool ap_random_bssid_enabled;
22604 	QDF_STATUS status;
22605 	int errno;
22606 	uint8_t mac_addr[QDF_MAC_ADDR_SIZE];
22607 	bool eht_capab;
22608 	struct wlan_hdd_link_info *link_info = adapter->deflink;
22609 
22610 	hdd_enter();
22611 
22612 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
22613 		hdd_err("Command not allowed in FTM mode");
22614 		return -EINVAL;
22615 	}
22616 
22617 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22618 	errno = wlan_hdd_validate_context(hdd_ctx);
22619 	if (errno)
22620 		return errno;
22621 
22622 	if (wlan_hdd_is_mon_concurrency())
22623 		return -EINVAL;
22624 
22625 	wlan_hdd_lpc_handle_concurrency(hdd_ctx, false);
22626 
22627 	if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) &&
22628 	    !hdd_lpc_is_work_scheduled(hdd_ctx))
22629 		return -EINVAL;
22630 
22631 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
22632 		   TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
22633 		   link_info->vdev_id, type);
22634 
22635 	status = hdd_nl_to_qdf_iface_type(type, &new_mode);
22636 	if (QDF_IS_STATUS_ERROR(status))
22637 		return qdf_status_to_os_return(status);
22638 
22639 	/* A userspace issue leads to it sending a 'change to station mode'
22640 	 * request on a "p2p" device, expecting the driver do execute a 'change
22641 	 * to p2p-device mode' request instead. The (unfortunate) work around
22642 	 * here is implemented by overriding the new mode if the net_device name
22643 	 * starts with "p2p" and the requested mode was station.
22644 	 */
22645 	if (strnstr(ndev->name, "p2p", 3) && new_mode == QDF_STA_MODE)
22646 		new_mode = QDF_P2P_DEVICE_MODE;
22647 
22648 	hdd_debug("Changing mode for '%s' from %s to %s",
22649 		  ndev->name,
22650 		  qdf_opmode_str(adapter->device_mode),
22651 		  qdf_opmode_str(new_mode));
22652 
22653 	errno = hdd_trigger_psoc_idle_restart(hdd_ctx);
22654 	if (errno) {
22655 		hdd_err("Failed to restart psoc; errno:%d", errno);
22656 		return -EINVAL;
22657 	}
22658 
22659 	/* Reset the current device mode bit mask */
22660 	policy_mgr_clear_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
22661 
22662 	if (hdd_is_client_mode(adapter->device_mode)) {
22663 		if (adapter->device_mode == QDF_STA_MODE)
22664 			hdd_cleanup_conn_info(link_info);
22665 
22666 		if (hdd_is_client_mode(new_mode)) {
22667 			errno = hdd_change_adapter_mode(adapter, new_mode);
22668 			if (errno) {
22669 				hdd_err("change intf mode fail %d", errno);
22670 				goto err;
22671 			}
22672 		} else if (hdd_is_ap_mode(new_mode)) {
22673 			if (new_mode == QDF_P2P_GO_MODE)
22674 				wlan_hdd_cleanup_remain_on_channel_ctx(link_info);
22675 
22676 			hdd_stop_adapter(hdd_ctx, adapter);
22677 			hdd_deinit_adapter(hdd_ctx, adapter, true);
22678 			memset(&link_info->session, 0,
22679 			       sizeof(link_info->session));
22680 			adapter->device_mode = new_mode;
22681 
22682 			status = ucfg_mlme_get_ap_random_bssid_enable(
22683 						hdd_ctx->psoc,
22684 						&ap_random_bssid_enabled);
22685 			if (QDF_IS_STATUS_ERROR(status))
22686 				return qdf_status_to_os_return(status);
22687 
22688 			if (adapter->device_mode == QDF_SAP_MODE &&
22689 			    ap_random_bssid_enabled) {
22690 				/* To meet Android requirements create
22691 				 * a randomized MAC address of the
22692 				 * form 02:1A:11:Fx:xx:xx
22693 				 */
22694 				memcpy(mac_addr, ndev->dev_addr,
22695 				       QDF_MAC_ADDR_SIZE);
22696 
22697 				get_random_bytes(&mac_addr[3], 3);
22698 				mac_addr[0] = 0x02;
22699 				mac_addr[1] = 0x1A;
22700 				mac_addr[2] = 0x11;
22701 				mac_addr[3] |= 0xF0;
22702 				memcpy(adapter->mac_addr.bytes, mac_addr,
22703 				       QDF_MAC_ADDR_SIZE);
22704 				qdf_net_update_net_device_dev_addr(ndev,
22705 								   mac_addr,
22706 								   QDF_MAC_ADDR_SIZE);
22707 
22708 				pr_info("wlan: Generated HotSpot BSSID "
22709 					QDF_MAC_ADDR_FMT "\n",
22710 					QDF_MAC_ADDR_REF(ndev->dev_addr));
22711 			}
22712 			hdd_set_ap_ops(adapter->dev);
22713 		} else {
22714 			hdd_err("Changing to device mode '%s' is not supported",
22715 				qdf_opmode_str(new_mode));
22716 			errno = -EOPNOTSUPP;
22717 			goto err;
22718 		}
22719 	} else if (hdd_is_ap_mode(adapter->device_mode)) {
22720 		if (hdd_is_client_mode(new_mode)) {
22721 			errno = hdd_change_adapter_mode(adapter, new_mode);
22722 			if (errno) {
22723 				hdd_err("change mode fail %d", errno);
22724 				goto err;
22725 			}
22726 		} else if (hdd_is_ap_mode(new_mode)) {
22727 			adapter->device_mode = new_mode;
22728 
22729 			/* avoid starting the adapter, since it never stopped */
22730 			iff_up = false;
22731 		} else {
22732 			hdd_err("Changing to device mode '%s' is not supported",
22733 				qdf_opmode_str(new_mode));
22734 			errno = -EOPNOTSUPP;
22735 			goto err;
22736 		}
22737 	} else {
22738 		hdd_err("Changing from device mode '%s' is not supported",
22739 			qdf_opmode_str(adapter->device_mode));
22740 		errno = -EOPNOTSUPP;
22741 		goto err;
22742 	}
22743 
22744 	ucfg_psoc_mlme_get_11be_capab(hdd_ctx->psoc, &eht_capab);
22745 	if (eht_capab && hdd_adapter_is_ml_adapter(adapter)) {
22746 		switch (adapter->device_mode) {
22747 		case QDF_SAP_MODE:
22748 			hdd_adapter_set_sl_ml_adapter(adapter);
22749 			adapter->active_links = 0x1;
22750 			break;
22751 		case QDF_STA_MODE:
22752 			hdd_adapter_clear_sl_ml_adapter(adapter);
22753 
22754 			status = hdd_adapter_update_mac_on_mode_change(adapter);
22755 			if (QDF_IS_STATUS_ERROR(status))
22756 				goto err;
22757 
22758 			adapter->active_links =
22759 					(1 << adapter->num_links_on_create) - 1;
22760 			break;
22761 		default:
22762 			hdd_adapter_clear_sl_ml_adapter(adapter);
22763 			adapter->active_links = 0x1;
22764 			break;
22765 		}
22766 	}
22767 
22768 	/* restart the adapter if it was up before the change iface request */
22769 	if (iff_up) {
22770 		errno = hdd_start_adapter(adapter, true);
22771 		if (errno) {
22772 			hdd_err("Failed to start adapter");
22773 			errno = -EINVAL;
22774 			goto err;
22775 		}
22776 	}
22777 
22778 	ndev->ieee80211_ptr->iftype = type;
22779 	hdd_lpass_notify_mode_change(link_info);
22780 err:
22781 	/* Set bitmask based on updated value */
22782 	policy_mgr_set_concurrency_mode(hdd_ctx->psoc, adapter->device_mode);
22783 
22784 	hdd_exit();
22785 
22786 	return errno;
22787 }
22788 
22789 static int _wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
22790 					   struct net_device *net_dev,
22791 					   enum nl80211_iftype type,
22792 					   u32 *flags,
22793 					   struct vif_params *params)
22794 {
22795 	int errno;
22796 	struct osif_vdev_sync *vdev_sync;
22797 
22798 	errno = osif_vdev_sync_trans_start(net_dev, &vdev_sync);
22799 	if (errno)
22800 		goto err;
22801 
22802 	errno = __wlan_hdd_cfg80211_change_iface(wiphy, net_dev, type,
22803 						 flags, params);
22804 
22805 	osif_vdev_sync_trans_stop(vdev_sync);
22806 
22807 	return errno;
22808 err:
22809 	/* In the SSR case, errno will be -EINVAL from
22810 	 * __dsc_vdev_can_trans with qdf_is_recovering()
22811 	 * is true, only change -EINVAL to -EBUSY to make
22812 	 * wpa_supplicant has chance to retry mode switch.
22813 	 * Meanwhile do not touch the errno from
22814 	 * __wlan_hdd_cfg80211_change_iface with this
22815 	 * change.
22816 	 */
22817 	if (errno && errno != -EAGAIN && errno != -EBUSY)
22818 		errno = -EBUSY;
22819 	return errno;
22820 }
22821 
22822 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
22823 /**
22824  * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
22825  * @wiphy: Pointer to the wiphy structure
22826  * @ndev: Pointer to the net device
22827  * @type: Interface type
22828  * @flags: Flags for change interface
22829  * @params: Pointer to change interface parameters
22830  *
22831  * Return: 0 for success, error number on failure.
22832  */
22833 static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
22834 					  struct net_device *ndev,
22835 					  enum nl80211_iftype type,
22836 					  u32 *flags,
22837 					  struct vif_params *params)
22838 {
22839 	return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
22840 					       flags, params);
22841 }
22842 #else
22843 static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
22844 					  struct net_device *ndev,
22845 					  enum nl80211_iftype type,
22846 					  struct vif_params *params)
22847 {
22848 	return _wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
22849 					       &params->flags, params);
22850 }
22851 #endif /* KERNEL_VERSION(4, 12, 0) */
22852 
22853 QDF_STATUS wlan_hdd_send_sta_authorized_event(
22854 					struct hdd_adapter *adapter,
22855 					struct hdd_context *hdd_ctx,
22856 					const struct qdf_mac_addr *mac_addr)
22857 {
22858 	struct sk_buff *vendor_event;
22859 	QDF_STATUS status;
22860 	struct nl80211_sta_flag_update sta_flags;
22861 
22862 	hdd_enter();
22863 	if (!hdd_ctx) {
22864 		hdd_err("HDD context is null");
22865 		return QDF_STATUS_E_INVAL;
22866 	}
22867 
22868 	vendor_event =
22869 		wlan_cfg80211_vendor_event_alloc(
22870 			hdd_ctx->wiphy, &adapter->wdev, sizeof(sta_flags) +
22871 			QDF_MAC_ADDR_SIZE + NLMSG_HDRLEN,
22872 			QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES_INDEX,
22873 			GFP_KERNEL);
22874 	if (!vendor_event) {
22875 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
22876 		return QDF_STATUS_E_FAILURE;
22877 	}
22878 
22879 	qdf_mem_zero(&sta_flags, sizeof(sta_flags));
22880 
22881 	sta_flags.mask |= BIT(NL80211_STA_FLAG_AUTHORIZED);
22882 	sta_flags.set = true;
22883 
22884 	status = nla_put(vendor_event,
22885 			 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS,
22886 			 sizeof(struct  nl80211_sta_flag_update),
22887 			 &sta_flags);
22888 	if (status) {
22889 		hdd_err("STA flag put fails");
22890 		wlan_cfg80211_vendor_free_skb(vendor_event);
22891 		return QDF_STATUS_E_FAILURE;
22892 	}
22893 	status = nla_put(vendor_event,
22894 			 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR,
22895 			 QDF_MAC_ADDR_SIZE, mac_addr->bytes);
22896 	if (status) {
22897 		hdd_err("STA MAC put fails");
22898 		wlan_cfg80211_vendor_free_skb(vendor_event);
22899 		return QDF_STATUS_E_FAILURE;
22900 	}
22901 
22902 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
22903 
22904 	hdd_exit();
22905 	return QDF_STATUS_SUCCESS;
22906 }
22907 
22908 #ifdef QCA_MULTIPASS_SUPPORT
22909 static int
22910 wlan_hdd_set_peer_vlan_config(struct hdd_adapter *adapter,
22911 			      struct wlan_objmgr_vdev *vdev,
22912 			      uint8_t *mac_addr,
22913 			      uint8_t vlan_id)
22914 {
22915 	ol_txrx_soc_handle soc_txrx_handle;
22916 	cdp_config_param_type val;
22917 	QDF_STATUS status;
22918 
22919 	soc_txrx_handle = wlan_psoc_get_dp_handle(wlan_vdev_get_psoc(vdev));
22920 
22921 	cdp_peer_set_vlan_id(soc_txrx_handle,
22922 			     wlan_vdev_get_id(vdev),
22923 			     mac_addr, vlan_id);
22924 
22925 	val.cdp_peer_param_isolation = true;
22926 
22927 	cdp_txrx_set_peer_param(soc_txrx_handle,
22928 				wlan_vdev_get_id(vdev),
22929 				mac_addr,
22930 				CDP_CONFIG_ISOLATION,
22931 				val);
22932 
22933 	status = ucfg_mlme_peer_config_vlan(vdev, mac_addr);
22934 	if (QDF_IS_STATUS_ERROR(status))
22935 		return -EINVAL;
22936 
22937 	return 0;
22938 }
22939 
22940 static void
22941 wlan_hdd_set_vlan_id(struct hdd_sta_info_obj *sta_info_list,
22942 		     uint8_t *mac, struct station_parameters *params)
22943 {
22944 	struct hdd_station_info *sta_info;
22945 
22946 	if (!params->vlan_id)
22947 		return;
22948 
22949 	sta_info =
22950 	hdd_get_sta_info_by_mac(sta_info_list,
22951 				mac,
22952 				STA_INFO_SOFTAP_GET_STA_INFO);
22953 	if (!sta_info) {
22954 		hdd_err("Failed to find right station MAC: "
22955 			  QDF_MAC_ADDR_FMT,
22956 			  QDF_MAC_ADDR_REF(mac));
22957 		return;
22958 	}
22959 
22960 	sta_info->vlan_id = params->vlan_id;
22961 
22962 	hdd_put_sta_info_ref(sta_info_list, &sta_info, true,
22963 			     STA_INFO_SOFTAP_GET_STA_INFO);
22964 }
22965 
22966 static QDF_STATUS
22967 wlan_hdd_set_vlan_config(struct hdd_adapter *adapter,
22968 			 uint8_t *mac)
22969 {
22970 	int ret;
22971 	struct hdd_station_info *sta_info;
22972 
22973 	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
22974 					   (uint8_t *)mac,
22975 					   STA_INFO_SOFTAP_GET_STA_INFO);
22976 
22977 	if (!sta_info) {
22978 		hdd_err("Failed to find right station MAC:"
22979 			QDF_MAC_ADDR_FMT,
22980 			QDF_MAC_ADDR_REF((uint8_t *)mac));
22981 			return QDF_STATUS_E_INVAL;
22982 	}
22983 
22984 	if (!sta_info->vlan_id) {
22985 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
22986 				     true,
22987 				     STA_INFO_SOFTAP_GET_STA_INFO);
22988 		return QDF_STATUS_E_INVAL;
22989 	}
22990 
22991 	ret = wlan_hdd_set_peer_vlan_config(adapter,
22992 					    adapter->deflink->vdev,
22993 					    mac,
22994 					    sta_info->vlan_id);
22995 	if (ret < 0) {
22996 		hdd_err("Unable to send peer vlan config");
22997 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
22998 				     true,
22999 				     STA_INFO_SOFTAP_GET_STA_INFO);
23000 		return QDF_STATUS_E_INVAL;
23001 	}
23002 
23003 	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
23004 			     true,  STA_INFO_SOFTAP_GET_STA_INFO);
23005 
23006 	return QDF_STATUS_SUCCESS;
23007 }
23008 #else
23009 static inline void
23010 wlan_hdd_set_vlan_id(struct hdd_sta_info_obj *sta_info_list,
23011 		     uint8_t *mac, struct station_parameters *params)
23012 {
23013 }
23014 
23015 static inline QDF_STATUS
23016 wlan_hdd_set_vlan_config(struct hdd_adapter *adapter,
23017 			 uint8_t *mac)
23018 {
23019 	return QDF_STATUS_SUCCESS;
23020 }
23021 #endif
23022 /**
23023  * __wlan_hdd_change_station() - change station
23024  * @wiphy: Pointer to the wiphy structure
23025  * @dev: Pointer to the net device.
23026  * @mac: bssid
23027  * @params: Pointer to station parameters
23028  *
23029  * Return: 0 for success, error number on failure.
23030  */
23031 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
23032 static int __wlan_hdd_change_station(struct wiphy *wiphy,
23033 				   struct net_device *dev,
23034 				   const uint8_t *mac,
23035 				   struct station_parameters *params)
23036 #else
23037 static int __wlan_hdd_change_station(struct wiphy *wiphy,
23038 				   struct net_device *dev,
23039 				   uint8_t *mac,
23040 				   struct station_parameters *params)
23041 #endif
23042 {
23043 	QDF_STATUS status = QDF_STATUS_SUCCESS;
23044 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
23045 	struct hdd_context *hdd_ctx;
23046 	struct hdd_station_ctx *sta_ctx;
23047 	struct hdd_ap_ctx *ap_ctx;
23048 	struct qdf_mac_addr sta_macaddr;
23049 	int ret;
23050 
23051 	hdd_enter();
23052 
23053 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
23054 		hdd_err("Command not allowed in FTM mode");
23055 		return -EINVAL;
23056 	}
23057 
23058 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
23059 		   TRACE_CODE_HDD_CHANGE_STATION,
23060 		   adapter->deflink->vdev_id, params->listen_interval);
23061 
23062 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
23063 		return -EINVAL;
23064 
23065 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23066 	ret = wlan_hdd_validate_context(hdd_ctx);
23067 	if (0 != ret)
23068 		return ret;
23069 
23070 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
23071 
23072 	qdf_mem_copy(sta_macaddr.bytes, mac, QDF_MAC_ADDR_SIZE);
23073 
23074 	wlan_hdd_set_vlan_id(&adapter->sta_info_list, (uint8_t *)mac, params);
23075 
23076 	if ((adapter->device_mode == QDF_SAP_MODE) ||
23077 	    (adapter->device_mode == QDF_P2P_GO_MODE)) {
23078 		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
23079 			ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
23080 			/*
23081 			 * For Encrypted SAP session, this will be done as
23082 			 * part of eSAP_STA_SET_KEY_EVENT
23083 			 */
23084 
23085 			if (ucfg_mlme_is_multipass_sap(hdd_ctx->psoc)) {
23086 				status =
23087 				wlan_hdd_set_vlan_config(adapter,
23088 							 (uint8_t *)mac);
23089 				if (QDF_IS_STATUS_ERROR(status))
23090 					return 0;
23091 			}
23092 
23093 			if (ap_ctx->encryption_type !=
23094 			    eCSR_ENCRYPT_TYPE_NONE) {
23095 				hdd_debug("Encrypt type %d, not setting peer authorized now",
23096 					  ap_ctx->encryption_type);
23097 				return 0;
23098 			}
23099 
23100 			status =
23101 				hdd_softap_change_sta_state(adapter,
23102 							    &sta_macaddr,
23103 							    OL_TXRX_PEER_STATE_AUTH);
23104 
23105 			if (status != QDF_STATUS_SUCCESS) {
23106 				hdd_debug("Not able to change TL state to AUTHENTICATED");
23107 				return -EINVAL;
23108 			}
23109 			status = wlan_hdd_send_sta_authorized_event(
23110 								adapter,
23111 								hdd_ctx,
23112 								&sta_macaddr);
23113 			if (status != QDF_STATUS_SUCCESS) {
23114 				return -EINVAL;
23115 			}
23116 		}
23117 	} else if ((adapter->device_mode == QDF_STA_MODE) ||
23118 		   (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
23119 		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
23120 #if defined(FEATURE_WLAN_TDLS)
23121 			struct wlan_objmgr_vdev *vdev;
23122 
23123 			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
23124 							   WLAN_OSIF_TDLS_ID);
23125 			if (!vdev)
23126 				return -EINVAL;
23127 			ret = wlan_cfg80211_tdls_update_peer(vdev, mac, params);
23128 			hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_TDLS_ID);
23129 #endif
23130 		}
23131 	}
23132 	hdd_exit();
23133 	return ret;
23134 }
23135 
23136 /**
23137  * wlan_hdd_change_station() - cfg80211 change station handler function
23138  * @wiphy: Pointer to the wiphy structure
23139  * @dev: Pointer to the net device.
23140  * @mac: bssid
23141  * @params: Pointer to station parameters
23142  *
23143  * This is the cfg80211 change station handler function which invokes
23144  * the internal function @__wlan_hdd_change_station with
23145  * SSR protection.
23146  *
23147  * Return: 0 for success, error number on failure.
23148  */
23149 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
23150 static int wlan_hdd_change_station(struct wiphy *wiphy,
23151 				   struct net_device *dev,
23152 				   const u8 *mac,
23153 				   struct station_parameters *params)
23154 #else
23155 static int wlan_hdd_change_station(struct wiphy *wiphy,
23156 				   struct net_device *dev,
23157 				   u8 *mac,
23158 				   struct station_parameters *params)
23159 #endif
23160 {
23161 	int errno;
23162 	struct osif_vdev_sync *vdev_sync;
23163 
23164 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
23165 	if (errno)
23166 		return errno;
23167 
23168 	errno = __wlan_hdd_change_station(wiphy, dev, mac, params);
23169 
23170 	osif_vdev_sync_op_stop(vdev_sync);
23171 
23172 	return errno;
23173 }
23174 
23175 #ifdef FEATURE_WLAN_ESE
23176 static bool hdd_is_krk_enc_type(uint32_t cipher_type)
23177 {
23178 	if (cipher_type == WLAN_CIPHER_SUITE_KRK)
23179 		return true;
23180 
23181 	return false;
23182 }
23183 #else
23184 static bool hdd_is_krk_enc_type(uint32_t cipher_type)
23185 {
23186 	return false;
23187 }
23188 #endif
23189 
23190 #if defined(FEATURE_WLAN_ESE) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
23191 static bool hdd_is_btk_enc_type(uint32_t cipher_type)
23192 {
23193 	if (cipher_type == WLAN_CIPHER_SUITE_BTK)
23194 		return true;
23195 
23196 	return false;
23197 }
23198 #else
23199 static bool hdd_is_btk_enc_type(uint32_t cipher_type)
23200 {
23201 	return false;
23202 }
23203 #endif
23204 
23205 #ifdef WLAN_FEATURE_11BE_MLO
23206 struct wlan_objmgr_vdev *wlan_key_get_link_vdev(struct hdd_adapter *adapter,
23207 						wlan_objmgr_ref_dbgid id,
23208 						int link_id)
23209 {
23210 	struct wlan_objmgr_vdev *vdev, *link_vdev;
23211 
23212 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, id);
23213 	if (!vdev)
23214 		return NULL;
23215 
23216 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
23217 		return vdev;
23218 
23219 	link_vdev = mlo_get_vdev_by_link_id(vdev, link_id, id);
23220 	hdd_objmgr_put_vdev_by_user(vdev, id);
23221 
23222 	return link_vdev;
23223 }
23224 
23225 void wlan_key_put_link_vdev(struct wlan_objmgr_vdev *link_vdev,
23226 			    wlan_objmgr_ref_dbgid id)
23227 {
23228 	if (!wlan_vdev_mlme_is_mlo_vdev(link_vdev)) {
23229 		hdd_objmgr_put_vdev_by_user(link_vdev, id);
23230 		return;
23231 	}
23232 
23233 	wlan_objmgr_vdev_release_ref(link_vdev, id);
23234 }
23235 #else
23236 struct wlan_objmgr_vdev *wlan_key_get_link_vdev(struct hdd_adapter *adapter,
23237 						wlan_objmgr_ref_dbgid id,
23238 						int link_id)
23239 {
23240 	struct wlan_objmgr_vdev *vdev;
23241 
23242 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, id);
23243 	if (!vdev)
23244 		return NULL;
23245 
23246 	return vdev;
23247 }
23248 
23249 void wlan_key_put_link_vdev(struct wlan_objmgr_vdev *link_vdev,
23250 			    wlan_objmgr_ref_dbgid id)
23251 {
23252 	hdd_objmgr_put_vdev_by_user(link_vdev, id);
23253 }
23254 #endif
23255 
23256 /*
23257  * FUNCTION: __wlan_hdd_cfg80211_get_key
23258  * This function is used to get the key information
23259  */
23260 
23261 static int wlan_hdd_add_key_sap(struct wlan_hdd_link_info *link_info,
23262 				bool pairwise, u8 key_index,
23263 				enum wlan_crypto_cipher_type cipher)
23264 {
23265 	struct wlan_objmgr_vdev *vdev;
23266 	int errno = 0;
23267 	struct hdd_hostapd_state *hostapd_state =
23268 		WLAN_HDD_GET_HOSTAP_STATE_PTR(link_info);
23269 
23270 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
23271 	if (!vdev)
23272 		return -EINVAL;
23273 
23274 	/* Do not send install key when sap restart is in progress. If there is
23275 	 * critical channel request handling going on, fw will stop that request
23276 	 * and will not send restart response
23277 	 */
23278 	if (wlan_vdev_is_restart_progress(vdev) == QDF_STATUS_SUCCESS) {
23279 		hdd_err("vdev: %d restart in progress", wlan_vdev_get_id(vdev));
23280 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
23281 		return -EINVAL;
23282 	}
23283 
23284 	if (hostapd_state->bss_state == BSS_START) {
23285 		errno =
23286 		wlan_cfg80211_crypto_add_key(vdev,
23287 					     (pairwise ?
23288 					      WLAN_CRYPTO_KEY_TYPE_UNICAST :
23289 					      WLAN_CRYPTO_KEY_TYPE_GROUP),
23290 					     key_index, true);
23291 		if (!errno)
23292 			wma_update_set_key(link_info->vdev_id, pairwise,
23293 					   key_index, cipher);
23294 	}
23295 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
23296 
23297 	return errno;
23298 }
23299 
23300 static int wlan_hdd_add_key_sta(struct wlan_objmgr_pdev *pdev,
23301 				struct wlan_hdd_link_info *link_info,
23302 				bool pairwise, u8 key_index, bool *ft_mode)
23303 {
23304 	struct wlan_objmgr_vdev *vdev;
23305 	int errno;
23306 	QDF_STATUS status;
23307 	struct hdd_adapter *adapter = link_info->adapter;
23308 
23309 	/* The supplicant may attempt to set the PTK once
23310 	 * pre-authentication is done. Save the key in the
23311 	 * UMAC and install it after association
23312 	 */
23313 	status = ucfg_cm_check_ft_status(pdev, link_info->vdev_id);
23314 	if (status == QDF_STATUS_SUCCESS) {
23315 		*ft_mode = true;
23316 		return 0;
23317 	}
23318 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
23319 	if (!vdev)
23320 		return -EINVAL;
23321 	errno = wlan_cfg80211_crypto_add_key(vdev, (pairwise ?
23322 					     WLAN_CRYPTO_KEY_TYPE_UNICAST :
23323 					     WLAN_CRYPTO_KEY_TYPE_GROUP),
23324 					     key_index, true);
23325 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
23326 	if (!errno && adapter->send_mode_change) {
23327 		wlan_hdd_send_mode_change_event();
23328 		adapter->send_mode_change = false;
23329 	}
23330 
23331 	return errno;
23332 }
23333 
23334 #ifdef WLAN_FEATURE_11BE_MLO
23335 static void
23336 wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc *psoc,
23337 			    struct hdd_adapter *adapter,
23338 			    struct wlan_objmgr_vdev *vdev,
23339 			    bool pairwise)
23340 {
23341 	struct qdf_mac_addr *link_addr;
23342 	uint8_t link_id;
23343 
23344 	if (adapter->device_mode != QDF_STA_MODE)
23345 		return;
23346 
23347 	if (pairwise &&
23348 	    wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
23349 	    mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
23350 					      wlan_vdev_get_id(vdev))) {
23351 		link_addr =
23352 		(struct qdf_mac_addr *)wlan_vdev_mlme_get_linkaddr(vdev);
23353 
23354 		if (!link_addr) {
23355 			crypto_err("link_addr NULL");
23356 			return;
23357 		}
23358 		link_id = wlan_vdev_get_link_id(vdev);
23359 		wlan_crypto_free_key_by_link_id(psoc, link_addr, link_id);
23360 	}
23361 }
23362 
23363 #else
23364 
23365 static void
23366 wlan_hdd_mlo_link_free_keys(struct wlan_objmgr_psoc *psoc,
23367 			    struct hdd_adapter *adapter,
23368 			    struct wlan_objmgr_vdev *vdev,
23369 			    bool pairwise)
23370 {
23371 }
23372 #endif
23373 
23374 #ifdef WLAN_FEATURE_11BE_MLO
23375 QDF_STATUS
23376 wlan_hdd_mlo_copy_partner_addr_from_mlie(struct wlan_objmgr_vdev *vdev,
23377 					 struct qdf_mac_addr *partner_mac)
23378 {
23379 	int i;
23380 	QDF_STATUS status;
23381 	struct wlan_mlo_dev_context *mlo_dev_ctx;
23382 	struct wlan_mlo_sta *sta_ctx;
23383 	struct mlo_link_info *partner_link_info;
23384 	struct element_info *assoc_rsp;
23385 	const uint8_t *ie_data_ptr;
23386 	size_t ie_data_len, ml_ie_len = 0;
23387 	uint8_t *ml_ie = NULL;
23388 	bool found = false;
23389 	struct mlo_partner_info partner_info = {0};
23390 
23391 	if (!vdev)
23392 		return QDF_STATUS_E_NULL_VALUE;
23393 
23394 	mlo_dev_ctx = vdev->mlo_dev_ctx;
23395 	if (!mlo_dev_ctx)
23396 		return QDF_STATUS_E_INVAL;
23397 
23398 	sta_ctx = mlo_dev_ctx->sta_ctx;
23399 	if (!sta_ctx)
23400 		return QDF_STATUS_E_INVAL;
23401 
23402 	mlo_dev_lock_acquire(mlo_dev_ctx);
23403 	assoc_rsp = &sta_ctx->assoc_rsp;
23404 
23405 	if (!assoc_rsp->len || !assoc_rsp->ptr ||
23406 	    assoc_rsp->len <= WLAN_ASSOC_RSP_IES_OFFSET) {
23407 		mlo_dev_lock_release(mlo_dev_ctx);
23408 		return QDF_STATUS_E_INVAL;
23409 	}
23410 
23411 	ie_data_len = assoc_rsp->len - WLAN_ASSOC_RSP_IES_OFFSET;
23412 	ie_data_ptr = assoc_rsp->ptr + WLAN_ASSOC_RSP_IES_OFFSET;
23413 	status = util_find_mlie((uint8_t *)ie_data_ptr, ie_data_len,
23414 				&ml_ie, &ml_ie_len);
23415 
23416 	if (QDF_IS_STATUS_ERROR(status) || !ml_ie) {
23417 		mlo_dev_lock_release(mlo_dev_ctx);
23418 		hdd_debug("ML IE not found %d", status);
23419 		return status;
23420 	}
23421 
23422 	status = util_get_bvmlie_persta_partner_info(ml_ie, ml_ie_len,
23423 						     &partner_info);
23424 	if (QDF_IS_STATUS_ERROR(status)) {
23425 		mlo_dev_lock_release(mlo_dev_ctx);
23426 		hdd_err("Unable to find per-sta profile in ML IE");
23427 		return status;
23428 	}
23429 	mlo_dev_lock_release(mlo_dev_ctx);
23430 
23431 	for (i = 0; i < partner_info.num_partner_links; i++) {
23432 		partner_link_info = &partner_info.partner_link_info[i];
23433 		if (partner_link_info->link_id == vdev->vdev_mlme.mlo_link_id) {
23434 			qdf_copy_macaddr(partner_mac,
23435 					 &partner_link_info->link_addr);
23436 			found = true;
23437 			break;
23438 		}
23439 	}
23440 
23441 	if (!partner_info.num_partner_links || !found)
23442 		status = QDF_STATUS_E_NOENT;
23443 
23444 	return status;
23445 }
23446 #endif
23447 
23448 #if defined(QCA_MULTIPASS_SUPPORT) && \
23449 	(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
23450 static void
23451 wlan_hdd_set_vlan_groupkey(ol_txrx_soc_handle soc_txrx_handle, uint16_t vdev_id,
23452 			   struct key_params *params, uint8_t key_index)
23453 {
23454 	if (params->vlan_id)
23455 		cdp_set_vlan_groupkey(soc_txrx_handle, vdev_id,
23456 				      params->vlan_id, key_index);
23457 }
23458 
23459 static int
23460 wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
23461 		  struct key_params *params, uint8_t key_index,
23462 		  uint8_t *vlan_key_idx)
23463 {
23464 	struct wlan_objmgr_psoc *psoc = NULL;
23465 	ol_txrx_soc_handle soc_txrx_handle;
23466 	uint16_t *vlan_map = sap_ctx->vlan_map;
23467 	uint8_t found = 0;
23468 	bool keyindex_valid;
23469 	int i = 0;
23470 
23471 	psoc = wlan_vdev_get_psoc(vdev);
23472 	if (!psoc) {
23473 		hdd_err("Unable to get psoc");
23474 		return -EINVAL;
23475 	}
23476 
23477 	for (i = 0; i < (MAX_VLAN * 2); i += 2) {
23478 		if (!vlan_map[i] || !vlan_map[i + 1]) {
23479 			found = 1;
23480 			break;
23481 		} else if ((vlan_map[i] == params->vlan_id) ||
23482 			   (vlan_map[i + 1] == params->vlan_id)) {
23483 			vlan_map[i] = 0;
23484 			vlan_map[i + 1] = 0;
23485 			found = 1;
23486 			break;
23487 		}
23488 	}
23489 
23490 	keyindex_valid = (i + key_index - 1) < (2 * MAX_VLAN) ? true : false;
23491 
23492 	if (found && keyindex_valid) {
23493 		soc_txrx_handle = wlan_psoc_get_dp_handle(psoc);
23494 		vlan_map[i + key_index - 1] = params->vlan_id;
23495 		wlan_hdd_set_vlan_groupkey(soc_txrx_handle,
23496 					   wlan_vdev_get_id(vdev),
23497 					   params,
23498 					   (i / 2) + 1);
23499 		*vlan_key_idx = (i + key_index - 1 + 8);
23500 		return 0;
23501 	}
23502 
23503 	hdd_err("Unable to find group key mapping for vlan_id: %d",
23504 		params->vlan_id);
23505 	return -EINVAL;
23506 }
23507 #else
23508 static int
23509 wlan_hdd_add_vlan(struct wlan_objmgr_vdev *vdev, struct sap_context *sap_ctx,
23510 		  struct key_params *params, uint8_t key_index,
23511 		  uint8_t *vlan_key_idx)
23512 {
23513 	return key_index;
23514 }
23515 #endif
23516 
23517 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
23518 static void wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev *vdev,
23519 					       struct hdd_context *hdd_ctx,
23520 					       u8 key_index, bool pairwise,
23521 					       struct key_params *params)
23522 {
23523 	struct mlo_link_info *mlo_link_info;
23524 	uint8_t link_info_iter = 0;
23525 
23526 	mlo_link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[0];
23527 	for (link_info_iter = 0; link_info_iter < WLAN_MAX_ML_BSS_LINKS;
23528 	     link_info_iter++, mlo_link_info++) {
23529 		if (qdf_is_macaddr_zero(&mlo_link_info->ap_link_addr) ||
23530 		    mlo_link_info->link_id == 0xFF)
23531 			continue;
23532 			hdd_debug(" Add pairwise key link id  %d ",
23533 				  mlo_link_info->link_id);
23534 			wlan_cfg80211_store_link_key(
23535 				hdd_ctx->psoc, key_index,
23536 				(pairwise ? WLAN_CRYPTO_KEY_TYPE_UNICAST :
23537 				WLAN_CRYPTO_KEY_TYPE_GROUP),
23538 				(uint8_t *)mlo_link_info->ap_link_addr.bytes,
23539 				params, &mlo_link_info->link_addr,
23540 				mlo_link_info->link_id);
23541 	}
23542 }
23543 
23544 static bool
23545 wlan_hdd_mlo_defer_set_keys(struct hdd_adapter *adapter,
23546 			    struct wlan_objmgr_vdev *vdev,
23547 			    struct qdf_mac_addr *mac_address)
23548 {
23549 	uint8_t link_id;
23550 
23551 	if (!adapter)
23552 		return false;
23553 
23554 	if (!vdev || !vdev->mlo_dev_ctx)
23555 		return false;
23556 
23557 	link_id = wlan_vdev_get_link_id(vdev);
23558 
23559 	if ((adapter->device_mode == QDF_STA_MODE) &&
23560 	    ((!wlan_cm_is_vdev_connected(vdev)) ||
23561 	    (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
23562 	     mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
23563 					       wlan_vdev_get_id(vdev))))) {
23564 		hdd_debug("MLO:Defer set keys for link_id %d", link_id);
23565 		mlo_defer_set_keys(vdev, link_id, true);
23566 		return true;
23567 	}
23568 
23569 	return false;
23570 }
23571 
23572 #else
23573 
23574 static void wlan_hdd_mlo_link_add_pairwise_key(struct wlan_objmgr_vdev *vdev,
23575 					       struct hdd_context *hdd_ctx,
23576 					       u8 key_index, bool pairwise,
23577 					       struct key_params *params)
23578 {
23579 }
23580 
23581 static bool
23582 wlan_hdd_mlo_defer_set_keys(struct hdd_adapter *adapter,
23583 			    struct wlan_objmgr_vdev *vdev,
23584 			    struct qdf_mac_addr *mac_address)
23585 {
23586 	return false;
23587 }
23588 
23589 #endif
23590 
23591 static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
23592 				 struct wlan_objmgr_vdev *vdev, u8 key_index,
23593 				 bool pairwise, const u8 *mac_addr,
23594 				 struct key_params *params, int link_id,
23595 				 struct wlan_hdd_link_info *link_info)
23596 {
23597 	QDF_STATUS status;
23598 	struct wlan_objmgr_peer *peer;
23599 	struct hdd_context *hdd_ctx;
23600 	struct qdf_mac_addr mac_address;
23601 	int32_t cipher_cap, ucast_cipher = 0;
23602 	int errno = 0;
23603 	enum wlan_crypto_cipher_type cipher;
23604 	bool ft_mode = false;
23605 	uint8_t keyidx;
23606 	struct hdd_ap_ctx *hdd_ap_ctx;
23607 	struct sap_context *sap_ctx;
23608 	struct hdd_adapter *adapter = link_info->adapter;
23609 
23610 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23611 
23612 	if (hdd_is_btk_enc_type(params->cipher))
23613 		return sme_add_key_btk(mac_handle, wlan_vdev_get_id(vdev),
23614 				       params->key, params->key_len);
23615 	if (hdd_is_krk_enc_type(params->cipher))
23616 		return sme_add_key_krk(mac_handle, wlan_vdev_get_id(vdev),
23617 				       params->key, params->key_len);
23618 
23619 	if (!pairwise && ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) ||
23620 	   (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE))) {
23621 		peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_ID);
23622 		if (peer) {
23623 			qdf_mem_copy(mac_address.bytes,
23624 				     wlan_peer_get_macaddr(peer),
23625 				     QDF_MAC_ADDR_SIZE);
23626 			wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
23627 		} else if (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
23628 			   adapter->device_mode == QDF_STA_MODE) {
23629 			status = wlan_objmgr_vdev_try_get_ref(vdev,
23630 							      WLAN_OSIF_ID);
23631 			if (QDF_IS_STATUS_ERROR(status)) {
23632 				hdd_err("Failed to get vdev ref");
23633 				return qdf_status_to_os_return(status);
23634 			}
23635 			status = wlan_hdd_mlo_copy_partner_addr_from_mlie(
23636 							vdev, &mac_address);
23637 			wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
23638 			if (QDF_IS_STATUS_ERROR(status)) {
23639 				hdd_err("Failed to get peer address from ML IEs");
23640 				return qdf_status_to_os_return(status);
23641 			}
23642 			goto done;
23643 		} else {
23644 			hdd_err("Peer is null return");
23645 			return -EINVAL;
23646 		}
23647 
23648 		status = mlo_get_link_mac_addr_from_reassoc_rsp(vdev,
23649 								&mac_address);
23650 		if (QDF_IS_STATUS_ERROR(status)) {
23651 			peer = wlan_objmgr_vdev_try_get_bsspeer(vdev,
23652 								WLAN_OSIF_ID);
23653 			if (!peer) {
23654 				hdd_err("Peer is null return");
23655 				return -EINVAL;
23656 			}
23657 			qdf_mem_copy(mac_address.bytes,
23658 				     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
23659 			wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
23660 		}
23661 	} else {
23662 		if (mac_addr)
23663 			qdf_mem_copy(mac_address.bytes,
23664 				     mac_addr,
23665 				     QDF_MAC_ADDR_SIZE);
23666 	}
23667 
23668 done:
23669 	wlan_hdd_mlo_link_free_keys(hdd_ctx->psoc, adapter, vdev, pairwise);
23670 	if (pairwise && adapter->device_mode == QDF_STA_MODE &&
23671 	    wlan_vdev_mlme_is_mlo_vdev(vdev) &&
23672 	    !wlan_vdev_mlme_is_tdls_vdev(vdev)) {
23673 		wlan_hdd_mlo_link_add_pairwise_key(vdev, hdd_ctx, key_index,
23674 						   pairwise, params);
23675 
23676 	} else {
23677 		errno = wlan_cfg80211_store_key(
23678 					vdev, key_index,
23679 					(pairwise ?
23680 					WLAN_CRYPTO_KEY_TYPE_UNICAST :
23681 					WLAN_CRYPTO_KEY_TYPE_GROUP),
23682 					mac_address.bytes, params);
23683 	}
23684 
23685 	if (wlan_hdd_mlo_defer_set_keys(adapter, vdev, &mac_address))
23686 		return 0;
23687 
23688 	cipher_cap = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_CIPHER_CAP);
23689 	if (errno)
23690 		return errno;
23691 	cipher = osif_nl_to_crypto_cipher_type(params->cipher);
23692 	QDF_SET_PARAM(ucast_cipher, cipher);
23693 	if (pairwise)
23694 		wma_set_peer_ucast_cipher(mac_address.bytes,
23695 					  ucast_cipher, cipher_cap);
23696 
23697 	cdp_peer_flush_frags(cds_get_context(QDF_MODULE_ID_SOC),
23698 			     wlan_vdev_get_id(vdev), mac_address.bytes);
23699 
23700 	switch (adapter->device_mode) {
23701 	case QDF_SAP_MODE:
23702 	case QDF_P2P_GO_MODE:
23703 		hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(link_info);
23704 		if (hdd_ap_ctx->during_auth_offload) {
23705 			hdd_err("don't need install key during auth");
23706 			return -EINVAL;
23707 		}
23708 
23709 		keyidx = key_index;
23710 
23711 		if (ucfg_mlme_is_multipass_sap(hdd_ctx->psoc) &&
23712 		    params->vlan_id) {
23713 			sap_ctx = hdd_ap_ctx->sap_context;
23714 			errno = wlan_hdd_add_vlan(vdev, sap_ctx, params,
23715 						  key_index, &keyidx);
23716 			if (errno < 0)
23717 				return errno;
23718 		}
23719 
23720 		errno = wlan_hdd_add_key_sap(link_info, pairwise,
23721 					     keyidx, cipher);
23722 
23723 		break;
23724 	case QDF_STA_MODE:
23725 	case QDF_P2P_CLIENT_MODE:
23726 	case QDF_NAN_DISC_MODE:
23727 		errno = wlan_hdd_add_key_sta(hdd_ctx->pdev, link_info, pairwise,
23728 					     key_index, &ft_mode);
23729 		if (ft_mode)
23730 			return 0;
23731 		break;
23732 	default:
23733 		break;
23734 	}
23735 	if (!errno && (adapter->device_mode != QDF_SAP_MODE))
23736 		wma_update_set_key(wlan_vdev_get_id(vdev), pairwise, key_index,
23737 				   cipher);
23738 
23739 	hdd_exit();
23740 	return errno;
23741 }
23742 
23743 #ifdef WLAN_FEATURE_11BE_MLO
23744 QDF_STATUS wlan_hdd_send_key_vdev(struct wlan_objmgr_vdev *vdev,
23745 				  u8 key_index, bool pairwise,
23746 				  enum wlan_crypto_cipher_type cipher_type)
23747 {
23748 	struct wlan_objmgr_peer *peer;
23749 	struct qdf_mac_addr mac_address;
23750 	int32_t cipher_cap, ucast_cipher = 0;
23751 	QDF_STATUS status = QDF_STATUS_SUCCESS;
23752 	int errno;
23753 	bool ft_mode = false;
23754 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
23755 	uint8_t vdev_id;
23756 	struct wlan_hdd_link_info *link_info;
23757 
23758 	if (!hdd_ctx) {
23759 		hdd_err("hdd_ctx is NULL");
23760 		return QDF_STATUS_E_NULL_VALUE;
23761 	}
23762 
23763 	vdev_id = wlan_vdev_get_id(vdev);
23764 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
23765 	if (!link_info) {
23766 		hdd_err("adapter is NULL for vdev %d", vdev_id);
23767 		return QDF_STATUS_E_NULL_VALUE;
23768 	}
23769 
23770 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) {
23771 		hdd_debug("vdev opmode is not STA mode");
23772 		return QDF_STATUS_E_INVAL;
23773 	}
23774 	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_OSIF_ID);
23775 	if (!peer) {
23776 		hdd_err("Peer is null return");
23777 		return QDF_STATUS_E_NULL_VALUE;
23778 	}
23779 	qdf_mem_copy(mac_address.bytes,
23780 		     wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
23781 	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
23782 
23783 	cipher_cap = wlan_crypto_get_param(vdev, WLAN_CRYPTO_PARAM_CIPHER_CAP);
23784 	QDF_SET_PARAM(ucast_cipher, cipher_type);
23785 	if (pairwise)
23786 		wma_set_peer_ucast_cipher(mac_address.bytes,
23787 					  ucast_cipher, cipher_cap);
23788 
23789 	cdp_peer_flush_frags(cds_get_context(QDF_MODULE_ID_SOC),
23790 			     vdev_id, mac_address.bytes);
23791 
23792 	errno = wlan_hdd_add_key_sta(hdd_ctx->pdev, link_info,
23793 				     pairwise, key_index, &ft_mode);
23794 	if (ft_mode)
23795 		return QDF_STATUS_SUCCESS;
23796 
23797 	if (!errno)
23798 		wma_update_set_key(vdev_id, pairwise, key_index, cipher_type);
23799 	else
23800 		status = QDF_STATUS_E_FAILURE;
23801 
23802 	return status;
23803 }
23804 #endif
23805 
23806 #if defined(WLAN_FEATURE_11BE_MLO) && \
23807 defined(CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT)
23808 struct wlan_objmgr_peer *
23809 wlan_hdd_ml_sap_get_peer(struct wlan_objmgr_vdev *vdev,
23810 			 const uint8_t *peer_mld)
23811 {
23812 	struct wlan_mlo_dev_context *ap_mlo_dev_ctx;
23813 	struct wlan_mlo_peer_list *mlo_peer_list;
23814 	struct wlan_mlo_peer_context *ml_peer;
23815 	struct wlan_mlo_link_peer_entry *peer_entry;
23816 	int i, pdev_id;
23817 	uint8_t *peer_mac;
23818 	struct wlan_objmgr_pdev *pdev;
23819 	struct wlan_objmgr_psoc *psoc;
23820 	struct wlan_objmgr_peer *peer = NULL;
23821 
23822 	if (!vdev)
23823 		return NULL;
23824 
23825 	pdev = wlan_vdev_get_pdev(vdev);
23826 
23827 	if (!pdev)
23828 		return NULL;
23829 
23830 	psoc = wlan_pdev_get_psoc(pdev);
23831 
23832 	if (!psoc)
23833 		return NULL;
23834 
23835 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
23836 
23837 	ap_mlo_dev_ctx = vdev->mlo_dev_ctx;
23838 	mlo_dev_lock_acquire(ap_mlo_dev_ctx);
23839 	mlo_peer_list = &ap_mlo_dev_ctx->mlo_peer_list;
23840 	ml_peerlist_lock_acquire(mlo_peer_list);
23841 	ml_peer = mlo_get_mlpeer(ap_mlo_dev_ctx,
23842 				 (struct qdf_mac_addr *)peer_mld);
23843 	if (!ml_peer) {
23844 		/* Peer is a legacy STA client, check peer list.
23845 		 * Treat the MLD address as legacy MAC address
23846 		 */
23847 		peer = wlan_objmgr_get_peer(psoc, pdev_id,
23848 					    peer_mld, WLAN_OSIF_ID);
23849 		goto out;
23850 	}
23851 
23852 	mlo_peer_lock_acquire(ml_peer);
23853 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
23854 		peer_entry = &ml_peer->peer_list[i];
23855 		if (!peer_entry)
23856 			continue;
23857 		/* Checking for VDEV match which will
23858 		 * be used for multiple VDEV case.
23859 		 */
23860 		if (vdev == wlan_peer_get_vdev(peer_entry->link_peer)) {
23861 			peer_mac = &peer_entry->link_peer->macaddr[0];
23862 			peer = wlan_objmgr_get_peer(psoc, pdev_id, peer_mac,
23863 						    WLAN_OSIF_ID);
23864 			break;
23865 		}
23866 	}
23867 	mlo_peer_lock_release(ml_peer);
23868 
23869 out:
23870 	ml_peerlist_lock_release(mlo_peer_list);
23871 	mlo_dev_lock_release(ap_mlo_dev_ctx);
23872 
23873 	return peer;
23874 }
23875 
23876 static int wlan_hdd_add_key_all_mlo_vdev(mac_handle_t mac_handle,
23877 					 struct wlan_objmgr_vdev *vdev,
23878 					 u8 key_index, bool pairwise,
23879 					 const u8 *mac_addr,
23880 					 struct key_params *params, int link_id,
23881 					 struct hdd_adapter *adapter)
23882 {
23883 	QDF_STATUS status;
23884 	struct hdd_context *hdd_ctx;
23885 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS];
23886 	struct wlan_objmgr_vdev *link_vdev;
23887 	struct qdf_mac_addr peer_mac;
23888 	struct wlan_objmgr_peer *peer = NULL;
23889 	int errno = 0;
23890 	uint16_t link, vdev_count = 0;
23891 	uint8_t vdev_id;
23892 	struct wlan_hdd_link_info *link_info;
23893 
23894 	/* if vdev mlme is mlo & pairwaise is set to true set same info for
23895 	 * both the links.
23896 	 */
23897 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23898 
23899 	mlo_sta_get_vdev_list(vdev, &vdev_count, wlan_vdev_list);
23900 	for (link = 0; link < vdev_count; link++) {
23901 		link_vdev = wlan_vdev_list[link];
23902 		vdev_id = wlan_vdev_get_id(link_vdev);
23903 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
23904 		if (!link_info) {
23905 			mlo_release_vdev_ref(link_vdev);
23906 			continue;
23907 		}
23908 		peer = NULL;
23909 		switch (adapter->device_mode) {
23910 		case QDF_SAP_MODE:
23911 			if (wlan_vdev_mlme_is_mlo_vdev(link_vdev))
23912 				peer = wlan_hdd_ml_sap_get_peer(
23913 						link_vdev,
23914 						mac_addr);
23915 			break;
23916 		case QDF_STA_MODE:
23917 		default:
23918 			status = mlo_get_link_mac_addr_from_reassoc_rsp(link_vdev,
23919 									&peer_mac);
23920 			if (QDF_IS_STATUS_ERROR(status))
23921 				peer = wlan_objmgr_vdev_try_get_bsspeer(link_vdev,
23922 									WLAN_OSIF_ID);
23923 			else
23924 				goto add_key;
23925 			break;
23926 		}
23927 
23928 		if (peer) {
23929 			qdf_mem_copy(peer_mac.bytes,
23930 				     wlan_peer_get_macaddr(peer),
23931 				     QDF_MAC_ADDR_SIZE);
23932 			wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
23933 
23934 		} else if (wlan_vdev_mlme_is_mlo_link_vdev(link_vdev) &&
23935 			   adapter->device_mode == QDF_STA_MODE) {
23936 			status = wlan_hdd_mlo_copy_partner_addr_from_mlie(
23937 							link_vdev, &peer_mac);
23938 			if (QDF_IS_STATUS_ERROR(status)) {
23939 				hdd_err("Failed to get peer address from ML IEs");
23940 				mlo_release_vdev_ref(link_vdev);
23941 				continue;
23942 			}
23943 		} else {
23944 			hdd_err("Peer is null");
23945 			mlo_release_vdev_ref(link_vdev);
23946 			continue;
23947 		}
23948 
23949 add_key:
23950 		errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
23951 					      pairwise, peer_mac.bytes,
23952 					      params, link_id, link_info);
23953 		mlo_release_vdev_ref(link_vdev);
23954 	}
23955 
23956 	return errno;
23957 }
23958 
23959 static int wlan_add_key_standby_link(struct hdd_adapter *adapter,
23960 				     struct wlan_objmgr_vdev *vdev,
23961 				     int link_id, u8 key_index,
23962 				     bool pairwise, struct key_params *params)
23963 {
23964 	int errno = 0;
23965 	struct hdd_context *hdd_ctx;
23966 	struct mlo_link_info *mlo_link_info;
23967 
23968 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
23969 
23970 	mlo_link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx,
23971 						       link_id);
23972 	if (!mlo_link_info)
23973 		return QDF_STATUS_E_FAILURE;
23974 
23975 	errno = wlan_cfg80211_store_link_key(
23976 			hdd_ctx->psoc, key_index,
23977 			(pairwise ? WLAN_CRYPTO_KEY_TYPE_UNICAST :
23978 			WLAN_CRYPTO_KEY_TYPE_GROUP),
23979 			(uint8_t *)mlo_link_info->ap_link_addr.bytes,
23980 			params,
23981 			&mlo_link_info->link_addr,
23982 			link_id);
23983 	hdd_debug("ml defer set key link id %d", link_id);
23984 	mlo_defer_set_keys(vdev, link_id, true);
23985 	return errno;
23986 }
23987 
23988 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
23989 				     struct wlan_objmgr_vdev *vdev,
23990 				     u8 key_index, bool pairwise,
23991 				     const u8 *mac_addr,
23992 				     struct key_params *params, int link_id,
23993 				     struct hdd_adapter *adapter)
23994 {
23995 	int errno = 0;
23996 	struct wlan_objmgr_vdev *link_vdev;
23997 	struct hdd_context *hdd_ctx;
23998 	uint8_t vdev_id;
23999 	QDF_STATUS status;
24000 	struct wlan_hdd_link_info *link_info;
24001 
24002 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
24003 		return errno;
24004 
24005 	vdev_id = wlan_vdev_get_id(vdev);
24006 	if (pairwise &&
24007 	    mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
24008 					      vdev_id)) {
24009 		status = mlo_roam_link_connect_notify(adapter->hdd_ctx->psoc,
24010 						      vdev_id);
24011 		if (QDF_IS_STATUS_ERROR(status)) {
24012 			hdd_err("Posting of link connect request failed");
24013 			return -EINVAL;
24014 		}
24015 	}
24016 
24017 	link_vdev = ucfg_tdls_get_tdls_link_vdev(vdev, WLAN_OSIF_TDLS_ID);
24018 	if (pairwise && link_id == -1 && !link_vdev)
24019 		return wlan_hdd_add_key_all_mlo_vdev(mac_handle, vdev,
24020 						     key_index, pairwise,
24021 						     mac_addr, params,
24022 						     link_id, adapter);
24023 
24024 	if (pairwise && link_id == -1 && link_vdev) {
24025 		hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24026 		link_info =
24027 		      hdd_get_link_info_by_vdev(hdd_ctx,
24028 						wlan_vdev_get_id(link_vdev));
24029 		link_id = wlan_vdev_get_link_id(link_vdev);
24030 		if (!link_info) {
24031 			ucfg_tdls_put_tdls_link_vdev(link_vdev,
24032 						     WLAN_OSIF_TDLS_ID);
24033 			hdd_err("couldn't set tdls key, link_id %d", link_id);
24034 			return -EINVAL;
24035 		}
24036 
24037 		errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
24038 					      pairwise, mac_addr, params,
24039 					      link_id, link_info);
24040 		ucfg_tdls_put_tdls_link_vdev(link_vdev, WLAN_OSIF_TDLS_ID);
24041 
24042 		return errno;
24043 	}
24044 
24045 	if (link_vdev)
24046 		ucfg_tdls_put_tdls_link_vdev(link_vdev, WLAN_OSIF_TDLS_ID);
24047 
24048 	if (wlan_vdev_get_link_id(adapter->deflink->vdev) == link_id) {
24049 		hdd_debug("add_key for same vdev: %d",
24050 			  adapter->deflink->vdev_id);
24051 		return wlan_hdd_add_key_vdev(mac_handle, vdev, key_index,
24052 					     pairwise, mac_addr, params,
24053 					     link_id, adapter->deflink);
24054 	}
24055 
24056 	link_vdev = wlan_key_get_link_vdev(adapter, WLAN_MLO_MGR_ID, link_id);
24057 	if (!link_vdev) {
24058 		hdd_err("couldn't get vdev for link_id :%d", link_id);
24059 		errno = wlan_add_key_standby_link(adapter, vdev, link_id,
24060 						  key_index, pairwise, params);
24061 		return errno;
24062 	}
24063 
24064 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24065 	link_info = hdd_get_link_info_by_vdev(hdd_ctx,
24066 					      wlan_vdev_get_id(link_vdev));
24067 	if (!link_info) {
24068 		hdd_err("couldn't set key for link_id:%d", link_id);
24069 		goto release_ref;
24070 	}
24071 
24072 	errno = wlan_hdd_add_key_vdev(mac_handle, link_vdev, key_index,
24073 				      pairwise, mac_addr, params,
24074 				      link_id, link_info);
24075 
24076 release_ref:
24077 	wlan_key_put_link_vdev(link_vdev, WLAN_MLO_MGR_ID);
24078 	return errno;
24079 }
24080 #elif defined(CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV)
24081 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
24082 				     struct wlan_objmgr_vdev *vdev,
24083 				     u8 key_index, bool pairwise,
24084 				     const u8 *mac_addr,
24085 				     struct key_params *params, int link_id,
24086 				     struct hdd_adapter *adapter)
24087 {
24088 	return wlan_hdd_add_key_vdev(mac_handle, vdev, key_index,
24089 				     pairwise, mac_addr, params,
24090 				     link_id, adapter->deflink);
24091 }
24092 #else
24093 static int wlan_hdd_add_key_mlo_vdev(mac_handle_t mac_handle,
24094 				     struct wlan_objmgr_vdev *vdev,
24095 				     u8 key_index, bool pairwise,
24096 				     const u8 *mac_addr,
24097 				     struct key_params *params, int link_id,
24098 				     struct hdd_adapter *adapter)
24099 {
24100 	return 0;
24101 }
24102 #endif
24103 
24104 static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24105 				       struct net_device *ndev,
24106 				       u8 key_index, bool pairwise,
24107 				       const u8 *mac_addr,
24108 				       struct key_params *params, int link_id)
24109 {
24110 	struct hdd_context *hdd_ctx;
24111 	mac_handle_t mac_handle;
24112 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
24113 	struct wlan_objmgr_vdev *vdev;
24114 	int errno;
24115 
24116 	hdd_enter();
24117 
24118 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
24119 		hdd_err("Command not allowed in FTM mode");
24120 		return -EINVAL;
24121 	}
24122 
24123 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24124 		return -EINVAL;
24125 
24126 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
24127 		   TRACE_CODE_HDD_CFG80211_ADD_KEY,
24128 		   adapter->deflink->vdev_id, params->key_len);
24129 
24130 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24131 	errno = wlan_hdd_validate_context(hdd_ctx);
24132 	if (errno)
24133 		return errno;
24134 
24135 	hdd_debug("converged Device_mode %s(%d) index %d, pairwise %d link_id %d",
24136 		  qdf_opmode_str(adapter->device_mode),
24137 		  adapter->device_mode, key_index, pairwise, link_id);
24138 	mac_handle = hdd_ctx->mac_handle;
24139 
24140 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
24141 	if (!vdev)
24142 		return -EINVAL;
24143 
24144 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
24145 		errno = wlan_hdd_add_key_vdev(mac_handle, vdev, key_index,
24146 					      pairwise, mac_addr, params,
24147 					      link_id, adapter->deflink);
24148 	else
24149 		errno = wlan_hdd_add_key_mlo_vdev(mac_handle, vdev, key_index,
24150 						  pairwise, mac_addr, params,
24151 						  link_id, adapter);
24152 
24153 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
24154 
24155 	return errno;
24156 }
24157 
24158 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24159 #ifdef CFG80211_SET_KEY_WITH_SRC_MAC
24160 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24161 				     struct wireless_dev *wdev,
24162 				     u8 key_index, bool pairwise,
24163 				     const u8 *src_addr,
24164 				     const u8 *mac_addr,
24165 				     struct key_params *params)
24166 #else
24167 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24168 				     struct wireless_dev *wdev,
24169 				     u8 key_index, bool pairwise,
24170 				     const u8 *mac_addr,
24171 				     struct key_params *params)
24172 #endif
24173 {
24174 	int errno = -EINVAL;
24175 	struct osif_vdev_sync *vdev_sync;
24176 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24177 						   struct hdd_adapter,
24178 						   wdev);
24179 	/* Legacy purposes */
24180 	int link_id = -1;
24181 
24182 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24183 		return errno;
24184 
24185 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24186 	if (errno)
24187 		return errno;
24188 
24189 	errno = __wlan_hdd_cfg80211_add_key(wiphy, adapter->dev, key_index,
24190 					    pairwise, mac_addr, params,
24191 					    link_id);
24192 
24193 	osif_vdev_sync_op_stop(vdev_sync);
24194 
24195 	return errno;
24196 }
24197 #elif defined(CFG80211_SET_KEY_WITH_SRC_MAC)
24198 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24199 				     struct net_device *ndev,
24200 				     u8 key_index, bool pairwise,
24201 				     const u8 *src_addr,
24202 				     const u8 *mac_addr,
24203 				     struct key_params *params)
24204 {
24205 	int errno;
24206 	int link_id = -1;
24207 	struct osif_vdev_sync *vdev_sync;
24208 
24209 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24210 	if (errno)
24211 		return errno;
24212 
24213 	errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
24214 					    mac_addr, params, link_id);
24215 
24216 	osif_vdev_sync_op_stop(vdev_sync);
24217 
24218 	return errno;
24219 }
24220 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
24221 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24222 				     struct net_device *ndev,
24223 				     int link_id, u8 key_index, bool pairwise,
24224 				     const u8 *mac_addr,
24225 				     struct key_params *params)
24226 {
24227 	int errno;
24228 	struct osif_vdev_sync *vdev_sync;
24229 
24230 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24231 	if (errno)
24232 		return errno;
24233 
24234 	errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
24235 					    mac_addr, params, link_id);
24236 
24237 	osif_vdev_sync_op_stop(vdev_sync);
24238 
24239 	return errno;
24240 }
24241 #else
24242 static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
24243 				     struct net_device *ndev,
24244 				     u8 key_index, bool pairwise,
24245 				     const u8 *mac_addr,
24246 				     struct key_params *params)
24247 {
24248 	int errno, link_id = -1;
24249 	struct osif_vdev_sync *vdev_sync;
24250 
24251 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24252 	if (errno)
24253 		return errno;
24254 
24255 	errno = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
24256 					    mac_addr, params, link_id);
24257 
24258 	osif_vdev_sync_op_stop(vdev_sync);
24259 
24260 	return errno;
24261 }
24262 #endif
24263 
24264 static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
24265 				       struct net_device *ndev,
24266 				       int link_id,
24267 				       u8 key_index, bool pairwise,
24268 				       const u8 *mac_addr, void *cookie,
24269 				       void (*callback)(void *cookie,
24270 							struct key_params *)
24271 				       )
24272 {
24273 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
24274 	struct key_params params;
24275 	eCsrEncryptionType enc_type;
24276 	int32_t ucast_cipher = 0;
24277 	struct wlan_objmgr_vdev *link_vdev;
24278 
24279 	hdd_enter();
24280 
24281 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
24282 		hdd_err("Command not allowed in FTM mode");
24283 		return -EINVAL;
24284 	}
24285 
24286 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24287 		return -EINVAL;
24288 
24289 	hdd_debug("Device_mode %s(%d)",
24290 		  qdf_opmode_str(adapter->device_mode), adapter->device_mode);
24291 
24292 	memset(&params, 0, sizeof(params));
24293 
24294 	if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX +
24295 			  WLAN_CRYPTO_MAXBIGTKKEYIDX)) {
24296 		hdd_err("Invalid key index: %d", key_index);
24297 		return -EINVAL;
24298 	}
24299 
24300 	link_vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
24301 	if (!link_vdev) {
24302 		hdd_err("Invalid vdev for link_id :%d", link_id);
24303 		return -EINVAL;
24304 	}
24305 
24306 	if (link_vdev)
24307 		ucast_cipher = wlan_crypto_get_param(link_vdev,
24308 						WLAN_CRYPTO_PARAM_UCAST_CIPHER);
24309 
24310 	sme_fill_enc_type(&enc_type, ucast_cipher);
24311 
24312 	switch (enc_type) {
24313 	case eCSR_ENCRYPT_TYPE_NONE:
24314 		params.cipher = IW_AUTH_CIPHER_NONE;
24315 		break;
24316 
24317 	case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
24318 	case eCSR_ENCRYPT_TYPE_WEP40:
24319 		params.cipher = WLAN_CIPHER_SUITE_WEP40;
24320 		break;
24321 
24322 	case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
24323 	case eCSR_ENCRYPT_TYPE_WEP104:
24324 		params.cipher = WLAN_CIPHER_SUITE_WEP104;
24325 		break;
24326 
24327 	case eCSR_ENCRYPT_TYPE_TKIP:
24328 		params.cipher = WLAN_CIPHER_SUITE_TKIP;
24329 		break;
24330 
24331 	case eCSR_ENCRYPT_TYPE_AES:
24332 		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
24333 		break;
24334 	case eCSR_ENCRYPT_TYPE_AES_GCMP:
24335 		params.cipher = WLAN_CIPHER_SUITE_GCMP;
24336 		break;
24337 	case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
24338 		params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
24339 		break;
24340 	default:
24341 		params.cipher = IW_AUTH_CIPHER_NONE;
24342 		break;
24343 	}
24344 
24345 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
24346 		   TRACE_CODE_HDD_CFG80211_GET_KEY,
24347 		   wlan_vdev_get_id(link_vdev), params.cipher);
24348 
24349 	params.key_len = 0;
24350 	params.seq_len = 0;
24351 	params.seq = NULL;
24352 	params.key = NULL;
24353 	callback(cookie, &params);
24354 
24355 	wlan_key_put_link_vdev(link_vdev, WLAN_OSIF_ID);
24356 	hdd_exit();
24357 	return 0;
24358 }
24359 
24360 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24361 static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
24362 				     struct wireless_dev *wdev,
24363 				     u8 key_index, bool pairwise,
24364 				     const u8 *mac_addr, void *cookie,
24365 				     void (*callback)(void *cookie,
24366 						      struct key_params *)
24367 				     )
24368 {
24369 	int errno = -EINVAL;
24370 	struct osif_vdev_sync *vdev_sync;
24371 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24372 						   struct hdd_adapter,
24373 						   wdev);
24374 	int link_id = -1;
24375 
24376 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24377 		return errno;
24378 
24379 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24380 	if (errno)
24381 		return errno;
24382 
24383 	errno = __wlan_hdd_cfg80211_get_key(wiphy, adapter->dev, link_id,
24384 					    key_index,
24385 					    pairwise, mac_addr, cookie,
24386 					    callback);
24387 
24388 	osif_vdev_sync_op_stop(vdev_sync);
24389 
24390 	return errno;
24391 }
24392 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
24393 static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
24394 				     struct net_device *ndev,
24395 				     int link_id, u8 key_index, bool pairwise,
24396 				     const u8 *mac_addr, void *cookie,
24397 				     void (*callback)(void *cookie,
24398 						      struct key_params *)
24399 				     )
24400 {
24401 	int errno;
24402 	struct osif_vdev_sync *vdev_sync;
24403 
24404 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24405 	if (errno)
24406 		return errno;
24407 
24408 	errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, link_id, key_index,
24409 					    pairwise, mac_addr, cookie,
24410 					    callback);
24411 
24412 	osif_vdev_sync_op_stop(vdev_sync);
24413 
24414 	return errno;
24415 }
24416 #else
24417 static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
24418 				     struct net_device *ndev,
24419 				     u8 key_index, bool pairwise,
24420 				     const u8 *mac_addr, void *cookie,
24421 				     void (*callback)(void *cookie,
24422 						      struct key_params *)
24423 				     )
24424 {
24425 	int errno;
24426 	int link_id = -1;
24427 	struct osif_vdev_sync *vdev_sync;
24428 
24429 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24430 	if (errno)
24431 		return errno;
24432 
24433 	errno = __wlan_hdd_cfg80211_get_key(wiphy, ndev, link_id, key_index,
24434 					    pairwise, mac_addr, cookie,
24435 					    callback);
24436 
24437 	osif_vdev_sync_op_stop(vdev_sync);
24438 
24439 	return errno;
24440 }
24441 #endif
24442 
24443 /**
24444  * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
24445  * @wiphy: wiphy interface context
24446  * @ndev: pointer to net device
24447  * @key_index: Key index used in 802.11 frames
24448  * @pairwise: true if it is pairwise key
24449  * @mac_addr: Peer address
24450  *
24451  * This function is required for cfg80211_ops API.
24452  * It is used to delete the key information
24453  * Underlying hardware implementation does not have API to delete the
24454  * encryption key for normal peers. Currently delete keys are supported
24455  * only for PASN peers.
24456  * For other peers, it is automatically deleted when the peer is
24457  * removed. Hence this function currently does nothing.
24458  * Future implementation may interpret delete key operation to
24459  * replacing the key with a random junk value, effectively making it
24460  * useless.
24461  *
24462  * Return: status code, always 0.
24463  */
24464 
24465 static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
24466 				       struct net_device *ndev,
24467 				       u8 key_index,
24468 				       bool pairwise, const u8 *mac_addr)
24469 {
24470 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
24471 	struct wlan_objmgr_peer *peer;
24472 	struct qdf_mac_addr peer_mac;
24473 	enum wlan_peer_type peer_type;
24474 	QDF_STATUS status = QDF_STATUS_SUCCESS;
24475 	int ret;
24476 
24477 	hdd_enter();
24478 
24479 	if (!mac_addr) {
24480 		hdd_debug("Peer mac address is NULL");
24481 		hdd_exit();
24482 		return 0;
24483 	}
24484 
24485 	ret = wlan_hdd_validate_context(hdd_ctx);
24486 	if (ret)
24487 		return ret;
24488 
24489 	qdf_mem_copy(peer_mac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
24490 	if (qdf_is_macaddr_zero(&peer_mac) ||
24491 	    qdf_is_macaddr_broadcast(&peer_mac)) {
24492 		hdd_err("Invalid mac address");
24493 		ret = -EINVAL;
24494 		goto err;
24495 	}
24496 
24497 	peer = wlan_objmgr_get_peer_by_mac(hdd_ctx->psoc, peer_mac.bytes,
24498 					   WLAN_OSIF_ID);
24499 	if (peer) {
24500 		peer_type = wlan_peer_get_peer_type(peer);
24501 		if (peer_type == WLAN_PEER_RTT_PASN) {
24502 			status = wifi_pos_send_pasn_peer_deauth(hdd_ctx->psoc,
24503 								&peer_mac);
24504 			if (QDF_IS_STATUS_ERROR(status))
24505 				hdd_err("send_pasn_peer_deauth failed");
24506 
24507 			ret = qdf_status_to_os_return(status);
24508 		}
24509 		wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
24510 	}
24511 err:
24512 	hdd_exit();
24513 
24514 	return ret;
24515 }
24516 
24517 /**
24518  * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
24519  * @wiphy: Pointer to wiphy structure.
24520  * @wdev: Pointer to wireless_dev structure.
24521  * @key_index: key index
24522  * @pairwise: pairwise
24523  * @mac_addr: mac address
24524  *
24525  * This is the cfg80211 delete key handler function which invokes
24526  * the internal function @__wlan_hdd_cfg80211_del_key with
24527  * SSR protection.
24528  *
24529  * Return: 0 for success, error number on failure.
24530  */
24531 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24532 static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
24533 				     struct wireless_dev *wdev,
24534 				     u8 key_index,
24535 				     bool pairwise, const u8 *mac_addr)
24536 {
24537 	int errno = -EINVAL;
24538 	struct osif_vdev_sync *vdev_sync;
24539 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24540 						   struct hdd_adapter,
24541 						   wdev);
24542 
24543 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24544 		return errno;
24545 
24546 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24547 	if (errno)
24548 		return errno;
24549 
24550 	errno = __wlan_hdd_cfg80211_del_key(wiphy, adapter->dev, key_index,
24551 					    pairwise, mac_addr);
24552 
24553 	osif_vdev_sync_op_stop(vdev_sync);
24554 
24555 	return errno;
24556 }
24557 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
24558 static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
24559 				     struct net_device *dev,
24560 				     int link_id, u8 key_index,
24561 				     bool pairwise, const u8 *mac_addr)
24562 {
24563 	int errno;
24564 	struct osif_vdev_sync *vdev_sync;
24565 
24566 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
24567 	if (errno)
24568 		return errno;
24569 
24570 	errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
24571 					    pairwise, mac_addr);
24572 
24573 	osif_vdev_sync_op_stop(vdev_sync);
24574 
24575 	return errno;
24576 }
24577 #else
24578 static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
24579 				     struct net_device *dev,
24580 				     u8 key_index, bool pairwise,
24581 				     const u8 *mac_addr)
24582 {
24583 	int errno;
24584 	struct osif_vdev_sync *vdev_sync;
24585 
24586 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
24587 	if (errno)
24588 		return errno;
24589 
24590 	errno = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
24591 					    pairwise, mac_addr);
24592 
24593 	osif_vdev_sync_op_stop(vdev_sync);
24594 
24595 	return errno;
24596 }
24597 #endif
24598 static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
24599 					       struct net_device *ndev,
24600 					       int link_id,
24601 					       u8 key_index,
24602 					       bool unicast, bool multicast)
24603 {
24604 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
24605 	struct hdd_context *hdd_ctx;
24606 	struct qdf_mac_addr bssid = QDF_MAC_ADDR_BCAST_INIT;
24607 	struct hdd_ap_ctx *ap_ctx;
24608 	struct wlan_crypto_key *crypto_key;
24609 	struct wlan_objmgr_vdev *vdev;
24610 	int ret;
24611 	QDF_STATUS status;
24612 
24613 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
24614 		hdd_err("Command not allowed in FTM mode");
24615 		return -EINVAL;
24616 	}
24617 
24618 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24619 		return -EINVAL;
24620 
24621 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
24622 		   TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
24623 		   adapter->deflink->vdev_id, key_index);
24624 
24625 	hdd_debug("Device_mode %s(%d) key_index = %d",
24626 		  qdf_opmode_str(adapter->device_mode),
24627 		  adapter->device_mode, key_index);
24628 
24629 	if (key_index >= (WLAN_CRYPTO_MAXKEYIDX + WLAN_CRYPTO_MAXIGTKKEYIDX +
24630 			  WLAN_CRYPTO_MAXBIGTKKEYIDX)) {
24631 		hdd_err("Invalid key index: %d", key_index);
24632 		return -EINVAL;
24633 	}
24634 
24635 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24636 	ret = wlan_hdd_validate_context(hdd_ctx);
24637 
24638 	if (0 != ret)
24639 		return ret;
24640 
24641 	vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
24642 	if (!vdev)
24643 		return -EINVAL;
24644 
24645 	crypto_key = wlan_crypto_get_key(vdev, key_index);
24646 	if (!crypto_key) {
24647 		hdd_err("Invalid NULL key info");
24648 		ret = -EINVAL;
24649 		goto out;
24650 	}
24651 	hdd_debug("unicast %d, multicast %d cipher %d",
24652 		  unicast, multicast, crypto_key->cipher_type);
24653 	if (!IS_WEP_CIPHER(crypto_key->cipher_type)) {
24654 		ret = 0;
24655 		goto out;
24656 	}
24657 
24658 	if ((adapter->device_mode == QDF_STA_MODE) ||
24659 	    (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
24660 		ret =
24661 		wlan_cfg80211_crypto_add_key(vdev,
24662 					     (unicast ?
24663 					      WLAN_CRYPTO_KEY_TYPE_UNICAST :
24664 					      WLAN_CRYPTO_KEY_TYPE_GROUP),
24665 					     key_index, true);
24666 		wma_update_set_key(adapter->deflink->vdev_id, unicast,
24667 				   key_index, crypto_key->cipher_type);
24668 	}
24669 
24670 	if (adapter->device_mode == QDF_SAP_MODE ||
24671 	    adapter->device_mode == QDF_P2P_GO_MODE) {
24672 		status = wlan_cfg80211_set_default_key(vdev, key_index,
24673 						       &bssid);
24674 		if (QDF_IS_STATUS_ERROR(status)) {
24675 			hdd_err("ret fail status %d", ret);
24676 			ret = -EINVAL;
24677 			goto out;
24678 		}
24679 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
24680 		ap_ctx->wep_def_key_idx = key_index;
24681 	}
24682 
24683 out:
24684 	wlan_key_put_link_vdev(vdev, WLAN_OSIF_ID);
24685 	return ret;
24686 }
24687 
24688 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24689 static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
24690 					     struct wireless_dev *wdev,
24691 					     u8 key_index,
24692 					     bool unicast, bool multicast)
24693 {
24694 	int errno = -EINVAL;
24695 	struct osif_vdev_sync *vdev_sync;
24696 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24697 						   struct hdd_adapter,
24698 						   wdev);
24699 	int link_id = -1;
24700 
24701 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24702 		return errno;
24703 
24704 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24705 	if (errno)
24706 		return errno;
24707 
24708 	errno = __wlan_hdd_cfg80211_set_default_key(wiphy, adapter->dev,
24709 						    link_id, key_index,
24710 						    unicast, multicast);
24711 
24712 	osif_vdev_sync_op_stop(vdev_sync);
24713 
24714 	return errno;
24715 }
24716 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
24717 static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
24718 					     struct net_device *ndev,
24719 					     int link_id, u8 key_index,
24720 					     bool unicast, bool multicast)
24721 {
24722 	int errno;
24723 	struct osif_vdev_sync *vdev_sync;
24724 
24725 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24726 	if (errno)
24727 		return errno;
24728 
24729 	errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, link_id,
24730 						    key_index, unicast,
24731 						    multicast);
24732 
24733 	osif_vdev_sync_op_stop(vdev_sync);
24734 
24735 	return errno;
24736 }
24737 #else
24738 static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
24739 					     struct net_device *ndev,
24740 					     u8 key_index,
24741 					     bool unicast, bool multicast)
24742 {
24743 	int errno;
24744 	int link_id = -1;
24745 	struct osif_vdev_sync *vdev_sync;
24746 
24747 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24748 	if (errno)
24749 		return errno;
24750 
24751 	errno = __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, link_id,
24752 						    key_index, unicast,
24753 						    multicast);
24754 
24755 	osif_vdev_sync_op_stop(vdev_sync);
24756 
24757 	return errno;
24758 }
24759 #endif
24760 
24761 #if defined (CFG80211_BIGTK_CONFIGURATION_SUPPORT) || \
24762 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
24763 static int _wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
24764 						     struct net_device *ndev,
24765 						     u8 key_index)
24766 {
24767 	hdd_enter();
24768 	return 0;
24769 }
24770 
24771 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
24772 static int wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
24773 						    struct wireless_dev *wdev,
24774 						    u8 key_index)
24775 {
24776 	int errno = -EINVAL;
24777 	struct osif_vdev_sync *vdev_sync;
24778 	struct hdd_adapter *adapter = qdf_container_of(wdev,
24779 						   struct hdd_adapter,
24780 						   wdev);
24781 
24782 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
24783 		return errno;
24784 
24785 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
24786 	if (errno)
24787 		return errno;
24788 
24789 	errno = _wlan_hdd_cfg80211_set_default_beacon_key(wiphy, adapter->dev,
24790 							  key_index);
24791 
24792 	osif_vdev_sync_op_stop(vdev_sync);
24793 
24794 	return errno;
24795 }
24796 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
24797 static int wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
24798 						    struct net_device *ndev,
24799 						    int link_id, u8 key_index)
24800 {
24801 	int errno;
24802 	struct osif_vdev_sync *vdev_sync;
24803 
24804 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24805 	if (errno)
24806 		return errno;
24807 
24808 	errno = _wlan_hdd_cfg80211_set_default_beacon_key(wiphy, ndev,
24809 							  key_index);
24810 
24811 	osif_vdev_sync_op_stop(vdev_sync);
24812 
24813 	return errno;
24814 }
24815 #else
24816 static int wlan_hdd_cfg80211_set_default_beacon_key(struct wiphy *wiphy,
24817 						    struct net_device *ndev,
24818 						    u8 key_index)
24819 {
24820 	int errno;
24821 	struct osif_vdev_sync *vdev_sync;
24822 
24823 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24824 	if (errno)
24825 		return errno;
24826 
24827 	errno = _wlan_hdd_cfg80211_set_default_beacon_key(wiphy, ndev,
24828 							  key_index);
24829 
24830 	osif_vdev_sync_op_stop(vdev_sync);
24831 
24832 	return errno;
24833 }
24834 #endif
24835 #endif
24836 
24837 #ifdef FEATURE_MONITOR_MODE_SUPPORT
24838 static
24839 void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
24840 			   uint32_t op_freq,
24841 			   struct ch_params *ch_params)
24842 {
24843 	struct hdd_station_ctx *station_ctx =
24844 			 WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
24845 	struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
24846 	enum hdd_dot11_mode hdd_dot11_mode;
24847 	uint8_t ini_dot11_mode =
24848 			(WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
24849 
24850 	hdd_debug("Dot11Mode is %u", ini_dot11_mode);
24851 	switch (ini_dot11_mode) {
24852 	case eHDD_DOT11_MODE_AUTO:
24853 #ifdef WLAN_FEATURE_11BE
24854 	case eHDD_DOT11_MODE_11be:
24855 	case eHDD_DOT11_MODE_11be_ONLY:
24856 		if (sme_is_feature_supported_by_fw(DOT11BE))
24857 			hdd_dot11_mode = eHDD_DOT11_MODE_11be;
24858 		else
24859 #endif
24860 		if (sme_is_feature_supported_by_fw(DOT11AX))
24861 			hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
24862 		else if (sme_is_feature_supported_by_fw(DOT11AC))
24863 			hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
24864 		else
24865 			hdd_dot11_mode = eHDD_DOT11_MODE_11n;
24866 		break;
24867 	case eHDD_DOT11_MODE_11ax:
24868 	case eHDD_DOT11_MODE_11ax_ONLY:
24869 		if (sme_is_feature_supported_by_fw(DOT11AX))
24870 			hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
24871 		else if (sme_is_feature_supported_by_fw(DOT11AC))
24872 			hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
24873 		else
24874 			hdd_dot11_mode = eHDD_DOT11_MODE_11n;
24875 		break;
24876 	case eHDD_DOT11_MODE_11ac:
24877 	case eHDD_DOT11_MODE_11ac_ONLY:
24878 		if (sme_is_feature_supported_by_fw(DOT11AC))
24879 			hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
24880 		else
24881 			hdd_dot11_mode = eHDD_DOT11_MODE_11n;
24882 		break;
24883 	case eHDD_DOT11_MODE_11n:
24884 	case eHDD_DOT11_MODE_11n_ONLY:
24885 		hdd_dot11_mode = eHDD_DOT11_MODE_11n;
24886 		break;
24887 	default:
24888 		hdd_dot11_mode = ini_dot11_mode;
24889 		break;
24890 	}
24891 	ch_info->channel_width = ch_params->ch_width;
24892 	ch_info->phy_mode =
24893 		hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
24894 	ch_info->freq = op_freq;
24895 	ch_info->cb_mode = ch_params->ch_width;
24896 	hdd_debug("ch_info width %d, phymode %d channel freq %d",
24897 		  ch_info->channel_width, ch_info->phy_mode,
24898 		  ch_info->freq);
24899 }
24900 #else
24901 static
24902 void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
24903 			   uint32_t op_freq,
24904 			   struct ch_params *ch_params)
24905 {
24906 }
24907 #endif
24908 
24909 void hdd_select_cbmode(struct hdd_adapter *adapter, qdf_freq_t oper_freq,
24910 		       qdf_freq_t sec_ch_2g_freq, struct ch_params *ch_params)
24911 {
24912 	uint32_t sec_ch_freq = 0;
24913 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
24914 
24915 	/*
24916 	 * CDS api expects secondary channel for calculating
24917 	 * the channel params
24918 	 */
24919 	if (ch_params->ch_width == CH_WIDTH_40MHZ &&
24920 	    WLAN_REG_IS_24GHZ_CH_FREQ(oper_freq)) {
24921 		if (sec_ch_2g_freq) {
24922 			sec_ch_freq = sec_ch_2g_freq;
24923 		} else {
24924 			if (oper_freq >= 2412 && oper_freq <= 2432)
24925 				sec_ch_freq = oper_freq + 20;
24926 			else if (oper_freq >= 2437 && oper_freq <= 2472)
24927 				sec_ch_freq = oper_freq - 20;
24928 		}
24929 	}
24930 
24931 	/* This call decides required channel bonding mode */
24932 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev, oper_freq,
24933 						sec_ch_freq, ch_params,
24934 						REG_CURRENT_PWR_MODE);
24935 
24936 	if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE ||
24937 	    policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
24938 		hdd_mon_select_cbmode(adapter, oper_freq, ch_params);
24939 }
24940 
24941 /**
24942  * wlan_hdd_cfg80211_connect() - cfg80211 connect api
24943  * @wiphy: Pointer to wiphy
24944  * @ndev: Pointer to network device
24945  * @req: Pointer to cfg80211 connect request
24946  *
24947  * Return: 0 for success, non-zero for failure
24948  */
24949 static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
24950 				     struct net_device *ndev,
24951 				     struct cfg80211_connect_params *req)
24952 {
24953 	int errno;
24954 	struct osif_vdev_sync *vdev_sync;
24955 
24956 	errno = osif_vdev_sync_op_start(ndev, &vdev_sync);
24957 	if (errno)
24958 		return errno;
24959 
24960 	errno = wlan_hdd_cm_connect(wiphy, ndev, req);
24961 
24962 	osif_vdev_sync_op_stop(vdev_sync);
24963 
24964 	return errno;
24965 }
24966 
24967 /**
24968  * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
24969  * @wiphy: Pointer to wiphy
24970  * @dev: Pointer to network device
24971  * @reason: Disconnect reason code
24972  *
24973  * Return: 0 for success, non-zero for failure
24974  */
24975 static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
24976 					struct net_device *dev, u16 reason)
24977 {
24978 	int errno;
24979 	struct osif_vdev_sync *vdev_sync;
24980 
24981 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
24982 	if (errno)
24983 		return errno;
24984 
24985 	errno = wlan_hdd_cm_disconnect(wiphy, dev, reason);
24986 
24987 	osif_vdev_sync_op_stop(vdev_sync);
24988 
24989 	return errno;
24990 }
24991 
24992 /**
24993  * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
24994  * @wiphy: Pointer to wiphy
24995  * @changed: Parameters changed
24996  *
24997  * This function is used to set the phy parameters. RTS Threshold/FRAG
24998  * Threshold/Retry Count etc.
24999  *
25000  * Return: 0 for success, non-zero for failure
25001  */
25002 static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
25003 						u32 changed)
25004 {
25005 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
25006 	int status;
25007 
25008 	hdd_enter();
25009 
25010 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25011 		hdd_err("Command not allowed in FTM mode");
25012 		return -EINVAL;
25013 	}
25014 
25015 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25016 		   TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
25017 		   NO_SESSION, wiphy->rts_threshold);
25018 
25019 	status = wlan_hdd_validate_context(hdd_ctx);
25020 
25021 	if (0 != status)
25022 		return status;
25023 
25024 	if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
25025 		u32 rts_threshold = (wiphy->rts_threshold == -1) ?
25026 				     cfg_max(CFG_RTS_THRESHOLD) :
25027 				     wiphy->rts_threshold;
25028 
25029 		if ((cfg_min(CFG_RTS_THRESHOLD) > rts_threshold) ||
25030 		    (cfg_max(CFG_RTS_THRESHOLD) < rts_threshold)) {
25031 			hdd_err("Invalid RTS Threshold value: %u",
25032 				rts_threshold);
25033 			return -EINVAL;
25034 		}
25035 
25036 		if (0 != ucfg_mlme_set_rts_threshold(hdd_ctx->psoc,
25037 		    rts_threshold)) {
25038 			hdd_err("mlme_set_rts_threshold failed for val %u",
25039 				rts_threshold);
25040 			return -EIO;
25041 		}
25042 
25043 		hdd_debug("set rts threshold %u", rts_threshold);
25044 	}
25045 
25046 	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
25047 		u16 frag_threshold = (wiphy->frag_threshold == -1) ?
25048 				     cfg_max(CFG_FRAG_THRESHOLD) :
25049 				     wiphy->frag_threshold;
25050 
25051 		if ((cfg_min(CFG_FRAG_THRESHOLD) > frag_threshold) ||
25052 		    (cfg_max(CFG_FRAG_THRESHOLD) < frag_threshold)) {
25053 			hdd_err("Invalid frag_threshold value %hu",
25054 				frag_threshold);
25055 			return -EINVAL;
25056 		}
25057 
25058 		if (0 != ucfg_mlme_set_frag_threshold(hdd_ctx->psoc,
25059 						      frag_threshold)) {
25060 			hdd_err("mlme_set_frag_threshold failed for val %hu",
25061 				frag_threshold);
25062 			return -EIO;
25063 		}
25064 
25065 		hdd_debug("set frag threshold %hu", frag_threshold);
25066 	}
25067 
25068 	hdd_exit();
25069 	return 0;
25070 }
25071 
25072 /**
25073  * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
25074  * @wiphy: Pointer to wiphy
25075  * @changed: Parameters changed
25076  *
25077  * Return: 0 for success, non-zero for failure
25078  */
25079 static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
25080 {
25081 	struct osif_psoc_sync *psoc_sync;
25082 	int errno;
25083 
25084 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
25085 	if (errno)
25086 		return errno;
25087 
25088 	errno = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
25089 
25090 	osif_psoc_sync_op_stop(psoc_sync);
25091 
25092 	return errno;
25093 }
25094 
25095 /**
25096  * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
25097  *				     key
25098  * @wiphy: Pointer to wiphy
25099  * @netdev: Pointer to network device
25100  * @key_index: Key index
25101  *
25102  * Return: 0
25103  */
25104 static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
25105 					   struct net_device *netdev,
25106 					   u8 key_index)
25107 {
25108 	hdd_enter();
25109 	return 0;
25110 }
25111 
25112 /**
25113  * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
25114  *				wlan_hdd_set_default_mgmt_key
25115  * @wiphy: pointer to wiphy
25116  * @wdev: pointer to wireless_device structure
25117  * @key_index: key index
25118  *
25119  * Return: 0 on success, error number on failure
25120  */
25121 #ifdef CFG80211_KEY_INSTALL_SUPPORT_ON_WDEV
25122 static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
25123 					 struct wireless_dev *wdev,
25124 					 u8 key_index)
25125 {
25126 	int errno = -EINVAL;
25127 	struct osif_vdev_sync *vdev_sync;
25128 	struct hdd_adapter *adapter = qdf_container_of(wdev,
25129 						   struct hdd_adapter,
25130 						   wdev);
25131 
25132 	if (!adapter || wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25133 		return errno;
25134 
25135 	errno = osif_vdev_sync_op_start(adapter->dev, &vdev_sync);
25136 	if (errno)
25137 		return errno;
25138 
25139 	errno = __wlan_hdd_set_default_mgmt_key(wiphy, adapter->dev, key_index);
25140 
25141 	osif_vdev_sync_op_stop(vdev_sync);
25142 
25143 	return errno;
25144 }
25145 #elif defined(CFG80211_MLO_KEY_OPERATION_SUPPORT)
25146 static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
25147 					 struct net_device *netdev,
25148 					 int link_id, u8 key_index)
25149 {
25150 	int errno;
25151 	struct osif_vdev_sync *vdev_sync;
25152 
25153 	errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
25154 	if (errno)
25155 		return errno;
25156 
25157 	errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
25158 
25159 	osif_vdev_sync_op_stop(vdev_sync);
25160 
25161 	return errno;
25162 }
25163 #else
25164 static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
25165 					 struct net_device *netdev,
25166 					 u8 key_index)
25167 {
25168 	int errno;
25169 	struct osif_vdev_sync *vdev_sync;
25170 
25171 	errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
25172 	if (errno)
25173 		return errno;
25174 
25175 	errno = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
25176 
25177 	osif_vdev_sync_op_stop(vdev_sync);
25178 
25179 	return errno;
25180 }
25181 #endif
25182 
25183 /*
25184  * Default val of cwmin, this value is used to override the
25185  * incorrect user set value
25186  */
25187 #define DEFAULT_CWMIN 15
25188 
25189 /*
25190  * Default val of cwmax, this value is used to override the
25191  * incorrect user set value
25192  */
25193 #define DEFAULT_CWMAX 1023
25194 
25195 /**
25196  * __wlan_hdd_set_txq_params() - implementation of set tx queue params
25197  *				to configure internal EDCA parameters
25198  * @wiphy: Pointer to wiphy
25199  * @dev: Pointer to network device
25200  * @params: Pointer to tx queue parameters
25201  *
25202  * Return: 0
25203  */
25204 static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
25205 				   struct net_device *dev,
25206 				   struct ieee80211_txq_params *params)
25207 {
25208 	QDF_STATUS status;
25209 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25210 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25211 	mac_handle_t mac_handle;
25212 	tSirMacEdcaParamRecord txq_edca_params;
25213 	static const uint8_t ieee_ac_to_qca_ac[] = {
25214 		[IEEE80211_AC_VO] = QCA_WLAN_AC_VO,
25215 		[IEEE80211_AC_VI] = QCA_WLAN_AC_VI,
25216 		[IEEE80211_AC_BE] = QCA_WLAN_AC_BE,
25217 		[IEEE80211_AC_BK] = QCA_WLAN_AC_BK,
25218 	};
25219 
25220 	hdd_enter();
25221 
25222 	if (wlan_hdd_validate_context(hdd_ctx))
25223 		return -EINVAL;
25224 
25225 	mac_handle = hdd_ctx->mac_handle;
25226 	if (params->cwmin == 0 || params->cwmin > DEFAULT_CWMAX)
25227 		params->cwmin = DEFAULT_CWMIN;
25228 
25229 	if (params->cwmax < params->cwmin || params->cwmax > DEFAULT_CWMAX)
25230 		params->cwmax = DEFAULT_CWMAX;
25231 
25232 	txq_edca_params.cw.min = convert_cw(params->cwmin);
25233 	txq_edca_params.cw.max = convert_cw(params->cwmax);
25234 	txq_edca_params.aci.aifsn = params->aifs;
25235 	/* The txop is multiple of 32us units */
25236 	txq_edca_params.txoplimit = params->txop;
25237 	txq_edca_params.aci.aci =
25238 			ieee_ac_to_qca_ac[params->ac];
25239 
25240 	status = sme_update_session_txq_edca_params(mac_handle,
25241 						    adapter->deflink->vdev_id,
25242 						    &txq_edca_params);
25243 
25244 	hdd_exit();
25245 	return qdf_status_to_os_return(status);
25246 }
25247 
25248 /**
25249  * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
25250  * @wiphy: pointer to wiphy
25251  * @dev: pointer to net_device structure
25252  * @params: pointer to ieee80211_txq_params
25253  *
25254  * Return: 0 on success, error number on failure
25255  */
25256 static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
25257 				   struct net_device *dev,
25258 				   struct ieee80211_txq_params *params)
25259 {
25260 	int errno;
25261 	struct osif_vdev_sync *vdev_sync;
25262 
25263 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25264 	if (errno)
25265 		return errno;
25266 
25267 	errno = __wlan_hdd_set_txq_params(wiphy, dev, params);
25268 
25269 	osif_vdev_sync_op_stop(vdev_sync);
25270 
25271 	return errno;
25272 }
25273 
25274 /**
25275  * hdd_softap_deauth_current_sta() - Deauth current sta
25276  * @adapter: pointer to adapter structure
25277  * @sta_info: pointer to the current station info structure
25278  * @hapd_state: pointer to hostapd state structure
25279  * @param: pointer to del sta params
25280  *
25281  * Return: QDF_STATUS on success, corresponding QDF failure status on failure
25282  */
25283 static
25284 QDF_STATUS hdd_softap_deauth_current_sta(struct hdd_adapter *adapter,
25285 					 struct hdd_station_info *sta_info,
25286 					 struct hdd_hostapd_state *hapd_state,
25287 					 struct csr_del_sta_params *param)
25288 {
25289 	qdf_event_t *disassoc_event = &hapd_state->qdf_sta_disassoc_event;
25290 	struct hdd_context *hdd_ctx;
25291 	QDF_STATUS qdf_status;
25292 	struct hdd_station_info *tmp = NULL;
25293 
25294 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25295 	if (!hdd_ctx) {
25296 		hdd_err("hdd_ctx is NULL");
25297 		return QDF_STATUS_E_INVAL;
25298 	}
25299 
25300 	qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
25301 
25302 	if (!qdf_is_macaddr_broadcast(&param->peerMacAddr))
25303 		sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
25304 					    adapter->deflink->vdev_id,
25305 					    (uint8_t *)&param->peerMacAddr,
25306 					    param->reason_code, 0);
25307 
25308 	qdf_status = hdd_softap_sta_deauth(adapter, param);
25309 
25310 	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
25311 		if (qdf_is_macaddr_broadcast(&sta_info->sta_mac)) {
25312 			hdd_for_each_sta_ref_safe(
25313 					adapter->sta_info_list,
25314 					sta_info, tmp,
25315 					STA_INFO_SOFTAP_DEAUTH_CURRENT_STA) {
25316 				sta_info->is_deauth_in_progress = true;
25317 				hdd_put_sta_info_ref(
25318 					&adapter->sta_info_list,
25319 					&sta_info, true,
25320 					STA_INFO_SOFTAP_DEAUTH_CURRENT_STA);
25321 			}
25322 		} else {
25323 			sta_info->is_deauth_in_progress = true;
25324 		}
25325 		qdf_status = qdf_wait_for_event_completion(
25326 						disassoc_event,
25327 						SME_PEER_DISCONNECT_TIMEOUT);
25328 		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
25329 			hdd_warn("Deauth time expired");
25330 	} else {
25331 		sta_info->is_deauth_in_progress = false;
25332 		hdd_debug("STA removal failed for ::" QDF_MAC_ADDR_FMT,
25333 			  QDF_MAC_ADDR_REF(sta_info->sta_mac.bytes));
25334 		return QDF_STATUS_E_NOENT;
25335 	}
25336 	return QDF_STATUS_SUCCESS;
25337 }
25338 
25339 QDF_STATUS hdd_softap_deauth_all_sta(struct hdd_adapter *adapter,
25340 				     struct hdd_hostapd_state *hapd_state,
25341 				     struct csr_del_sta_params *param)
25342 {
25343 	QDF_STATUS status;
25344 	bool is_sap_bcast_deauth_enabled = false;
25345 	struct hdd_context *hdd_ctx;
25346 	struct hdd_station_info *sta_info, *tmp = NULL;
25347 
25348 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25349 	if (!hdd_ctx) {
25350 		hdd_err("hdd_ctx is NULL");
25351 		return QDF_STATUS_E_INVAL;
25352 	}
25353 
25354 	ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc,
25355 					       &is_sap_bcast_deauth_enabled);
25356 
25357 	hdd_debug("sap_bcast_deauth_enabled %d", is_sap_bcast_deauth_enabled);
25358 
25359 	if (is_sap_bcast_deauth_enabled) {
25360 		struct hdd_station_info bcast_sta_info;
25361 
25362 		qdf_set_macaddr_broadcast(&bcast_sta_info.sta_mac);
25363 		return hdd_softap_deauth_current_sta(adapter, &bcast_sta_info,
25364 						     hapd_state, param);
25365 	}
25366 
25367 	hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp,
25368 				  STA_INFO_SOFTAP_DEAUTH_ALL_STA) {
25369 		if (!sta_info->is_deauth_in_progress) {
25370 			hdd_debug("Delete STA with MAC:" QDF_MAC_ADDR_FMT,
25371 				  QDF_MAC_ADDR_REF(sta_info->sta_mac.bytes));
25372 
25373 			if (QDF_IS_ADDR_BROADCAST(sta_info->sta_mac.bytes)) {
25374 				hdd_put_sta_info_ref(&adapter->sta_info_list,
25375 						&sta_info, true,
25376 						STA_INFO_SOFTAP_DEAUTH_ALL_STA);
25377 				continue;
25378 			}
25379 
25380 			qdf_mem_copy(param->peerMacAddr.bytes,
25381 				     sta_info->sta_mac.bytes,
25382 				     QDF_MAC_ADDR_SIZE);
25383 			status =
25384 			    hdd_softap_deauth_current_sta(adapter, sta_info,
25385 							  hapd_state, param);
25386 			if (QDF_IS_STATUS_ERROR(status)) {
25387 				hdd_put_sta_info_ref(
25388 						&adapter->sta_info_list,
25389 						&sta_info, true,
25390 						STA_INFO_SOFTAP_DEAUTH_ALL_STA);
25391 				if (tmp)
25392 					hdd_put_sta_info_ref(
25393 						&adapter->sta_info_list,
25394 						&tmp, true,
25395 						STA_INFO_SOFTAP_DEAUTH_ALL_STA);
25396 				return status;
25397 			}
25398 		}
25399 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
25400 				     STA_INFO_SOFTAP_DEAUTH_ALL_STA);
25401 	}
25402 
25403 	return QDF_STATUS_SUCCESS;
25404 }
25405 
25406 /**
25407  * __wlan_hdd_cfg80211_del_station() - delete station v2
25408  * @wiphy: Pointer to wiphy
25409  * @dev: Underlying net device
25410  * @param: Pointer to delete station parameter
25411  *
25412  * Return: 0 for success, non-zero for failure
25413  */
25414 static
25415 int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
25416 				    struct net_device *dev,
25417 				    struct csr_del_sta_params *param)
25418 {
25419 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25420 	struct hdd_context *hdd_ctx;
25421 	struct hdd_hostapd_state *hapd_state;
25422 	uint8_t *mac;
25423 	struct hdd_station_info *sta_info;
25424 
25425 	hdd_enter();
25426 
25427 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25428 		hdd_err("Command not allowed in FTM mode");
25429 		return -EINVAL;
25430 	}
25431 
25432 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25433 		return -EINVAL;
25434 
25435 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25436 		   TRACE_CODE_HDD_CFG80211_DEL_STA,
25437 		   adapter->deflink->vdev_id, adapter->device_mode);
25438 
25439 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25440 	if (!hdd_ctx) {
25441 		hdd_err("hdd_ctx is NULL");
25442 		return -EINVAL;
25443 	}
25444 
25445 	mac = (uint8_t *) param->peerMacAddr.bytes;
25446 
25447 	if (QDF_SAP_MODE != adapter->device_mode &&
25448 	    QDF_P2P_GO_MODE != adapter->device_mode)
25449 		goto fn_end;
25450 
25451 	hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
25452 	if (!hapd_state) {
25453 		hdd_err("Hostapd State is Null");
25454 		return 0;
25455 	}
25456 
25457 	if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac)) {
25458 		if (!QDF_IS_STATUS_SUCCESS(hdd_softap_deauth_all_sta(adapter,
25459 								     hapd_state,
25460 								     param)))
25461 			goto fn_end;
25462 	} else {
25463 		if (param->reason_code == REASON_1X_AUTH_FAILURE) {
25464 			struct wlan_objmgr_vdev *vdev;
25465 
25466 			vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
25467 							   WLAN_DP_ID);
25468 			if (vdev) {
25469 				ucfg_dp_softap_check_wait_for_tx_eap_pkt(vdev,
25470 						(struct qdf_mac_addr *)mac);
25471 				hdd_objmgr_put_vdev_by_user(vdev, WLAN_DP_ID);
25472 			}
25473 		}
25474 
25475 		sta_info = hdd_get_sta_info_by_mac(
25476 						&adapter->sta_info_list,
25477 						mac,
25478 						STA_INFO_CFG80211_DEL_STATION);
25479 
25480 		if (!sta_info) {
25481 			hdd_debug("Skip DEL STA as this is not used::"
25482 				  QDF_MAC_ADDR_FMT,
25483 				  QDF_MAC_ADDR_REF(mac));
25484 			return -ENOENT;
25485 		}
25486 
25487 		if (sta_info->is_deauth_in_progress) {
25488 			hdd_debug("Skip DEL STA as deauth is in progress::"
25489 				  QDF_MAC_ADDR_FMT,
25490 				  QDF_MAC_ADDR_REF(mac));
25491 			hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info,
25492 					     true,
25493 					     STA_INFO_CFG80211_DEL_STATION);
25494 			return -ENOENT;
25495 		}
25496 
25497 		hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_FMT,
25498 			  QDF_MAC_ADDR_REF(mac));
25499 		hdd_softap_deauth_current_sta(adapter, sta_info, hapd_state,
25500 					      param);
25501 		hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
25502 				     STA_INFO_CFG80211_DEL_STATION);
25503 	}
25504 
25505 fn_end:
25506 	hdd_exit();
25507 	return 0;
25508 }
25509 
25510 #if defined(USE_CFG80211_DEL_STA_V2)
25511 int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac)
25512 {
25513 	struct station_del_parameters del_sta;
25514 
25515 	del_sta.mac = mac;
25516 	del_sta.subtype = IEEE80211_STYPE_DEAUTH >> 4;
25517 	del_sta.reason_code = WLAN_REASON_DEAUTH_LEAVING;
25518 
25519 	return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
25520 					     adapter->dev, &del_sta);
25521 }
25522 #else
25523 int wlan_hdd_del_station(struct hdd_adapter *adapter, const uint8_t *mac)
25524 {
25525 	return wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy,
25526 					     adapter->dev, mac);
25527 }
25528 #endif
25529 
25530 /**
25531  * _wlan_hdd_cfg80211_del_station() - delete station entry handler
25532  * @wiphy: Pointer to wiphy
25533  * @dev: net_device to operate against
25534  * @mac: binary mac address
25535  * @reason_code: reason for the deauthorization/disassociation
25536  * @subtype: management frame subtype to indicate removal
25537  *
25538  * Return: Errno
25539  */
25540 static int _wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
25541 					  struct net_device *dev,
25542 					  const uint8_t *mac,
25543 					  uint16_t reason_code,
25544 					  uint8_t subtype)
25545 {
25546 	int errno;
25547 	struct csr_del_sta_params delStaParams;
25548 	struct osif_vdev_sync *vdev_sync;
25549 
25550 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25551 	if (errno)
25552 		return errno;
25553 
25554 	wlansap_populate_del_sta_params(mac, reason_code, subtype,
25555 					&delStaParams);
25556 	errno = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
25557 
25558 	osif_vdev_sync_op_stop(vdev_sync);
25559 
25560 	return errno;
25561 }
25562 
25563 #ifdef USE_CFG80211_DEL_STA_V2
25564 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
25565 				  struct net_device *dev,
25566 				  struct station_del_parameters *param)
25567 {
25568 	if (!param)
25569 		return -EINVAL;
25570 
25571 	return _wlan_hdd_cfg80211_del_station(wiphy, dev, param->mac,
25572 					      param->reason_code,
25573 					      param->subtype);
25574 }
25575 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
25576 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
25577 				  const uint8_t *mac)
25578 {
25579 	uint16_t reason = REASON_DEAUTH_NETWORK_LEAVING;
25580 	uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
25581 
25582 	return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
25583 }
25584 #else
25585 int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
25586 				  uint8_t *mac)
25587 {
25588 	uint16_t reason = REASON_DEAUTH_NETWORK_LEAVING;
25589 	uint8_t subtype = SIR_MAC_MGMT_DEAUTH >> 4;
25590 
25591 	return _wlan_hdd_cfg80211_del_station(wiphy, dev, mac, reason, subtype);
25592 }
25593 #endif
25594 
25595 #ifdef CFG80211_LINK_STA_PARAMS_PRESENT
25596 static inline
25597 uint8_t wlan_hdd_get_link_id(struct station_parameters *params)
25598 {
25599 	return params->link_sta_params.link_id;
25600 }
25601 #else
25602 static inline
25603 uint8_t wlan_hdd_get_link_id(struct station_parameters *params)
25604 {
25605 	return 255;
25606 }
25607 #endif
25608 /**
25609  * __wlan_hdd_cfg80211_add_station() - add station
25610  * @wiphy: Pointer to wiphy
25611  * @dev: Pointer to network device
25612  * @mac: Pointer to station mac address
25613  * @params: Pointer to add station parameter
25614  *
25615  * Return: 0 for success, non-zero for failure
25616  */
25617 static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
25618 					   struct net_device *dev,
25619 					   const uint8_t *mac,
25620 					   struct station_parameters *params)
25621 {
25622 	int status = -EPERM;
25623 #ifdef FEATURE_WLAN_TDLS
25624 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25625 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
25626 	u32 mask, set;
25627 	uint8_t link_id;
25628 
25629 	hdd_enter();
25630 
25631 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25632 		hdd_err("Command not allowed in FTM mode");
25633 		return -EINVAL;
25634 	}
25635 
25636 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25637 		return -EINVAL;
25638 
25639 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25640 		   TRACE_CODE_HDD_CFG80211_ADD_STA,
25641 		   adapter->deflink->vdev_id, params->listen_interval);
25642 
25643 	if (0 != wlan_hdd_validate_context(hdd_ctx))
25644 		return -EINVAL;
25645 
25646 	mask = params->sta_flags_mask;
25647 	set = params->sta_flags_set;
25648 	link_id = wlan_hdd_get_link_id(params);
25649 	hdd_debug("mask 0x%x set 0x%x link_id %d " QDF_MAC_ADDR_FMT, mask, set,
25650 		  link_id, QDF_MAC_ADDR_REF(mac));
25651 
25652 	if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
25653 		if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
25654 			status = wlan_cfg80211_tdls_add_peer_mlo(adapter,
25655 								 mac, link_id);
25656 		}
25657 	}
25658 #endif
25659 	hdd_exit();
25660 	return status;
25661 }
25662 
25663 /**
25664  * wlan_hdd_cfg80211_add_station() - add station
25665  * @wiphy: Pointer to wiphy
25666  * @dev: Pointer to network device
25667  * @mac: Pointer to station mac address
25668  * @params: Pointer to add station parameter
25669  *
25670  * Return: 0 for success, non-zero for failure
25671  */
25672 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
25673 static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
25674 					 struct net_device *dev,
25675 					 const uint8_t *mac,
25676 					 struct station_parameters *params)
25677 #else
25678 static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
25679 					 struct net_device *dev, uint8_t *mac,
25680 					 struct station_parameters *params)
25681 #endif
25682 {
25683 	int errno;
25684 	struct osif_vdev_sync *vdev_sync;
25685 
25686 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
25687 	if (errno)
25688 		return errno;
25689 
25690 	errno = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
25691 
25692 	osif_vdev_sync_op_stop(vdev_sync);
25693 
25694 	return errno;
25695 }
25696 
25697 #if (defined(CFG80211_CONFIG_PMKSA_TIMER_PARAMS_SUPPORT) || \
25698 	     (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0)))
25699 static inline void
25700 hdd_fill_pmksa_lifetime(struct cfg80211_pmksa *pmksa,
25701 			struct wlan_crypto_pmksa *pmk_cache)
25702 {
25703 	pmk_cache->pmk_lifetime = pmksa->pmk_lifetime;
25704 	if (pmk_cache->pmk_lifetime > WLAN_CRYPTO_MAX_PMKID_LIFETIME)
25705 		pmk_cache->pmk_lifetime = WLAN_CRYPTO_MAX_PMKID_LIFETIME;
25706 
25707 	pmk_cache->pmk_lifetime_threshold = pmksa->pmk_reauth_threshold;
25708 	if (pmk_cache->pmk_lifetime_threshold >=
25709 	    WLAN_CRYPTO_MAX_PMKID_LIFETIME_THRESHOLD)
25710 		pmk_cache->pmk_lifetime_threshold =
25711 			WLAN_CRYPTO_MAX_PMKID_LIFETIME_THRESHOLD - 1;
25712 
25713 	hdd_debug("PMKSA: lifetime:%d threshold:%d",  pmk_cache->pmk_lifetime,
25714 		  pmk_cache->pmk_lifetime_threshold);
25715 }
25716 #else
25717 static inline void
25718 hdd_fill_pmksa_lifetime(struct cfg80211_pmksa *pmksa,
25719 			struct wlan_crypto_pmksa *src_pmk_cache)
25720 {}
25721 #endif
25722 
25723 static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
25724 					   struct wlan_crypto_pmksa *pmk_cache)
25725 {
25726 	QDF_STATUS result;
25727 	struct wlan_crypto_pmksa *pmksa;
25728 	struct wlan_objmgr_vdev *vdev;
25729 	mac_handle_t mac_handle;
25730 	struct hdd_context *hdd_ctx;
25731 
25732 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25733 	if (!hdd_ctx) {
25734 		hdd_err("HDD context is null");
25735 		return QDF_STATUS_E_INVAL;
25736 	}
25737 
25738 	if (wlan_hdd_validate_context(hdd_ctx))
25739 		return QDF_STATUS_E_INVAL;
25740 	mac_handle = hdd_ctx->mac_handle;
25741 
25742 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
25743 	if (!vdev)
25744 		return QDF_STATUS_E_FAILURE;
25745 
25746 	pmksa = qdf_mem_malloc(sizeof(*pmksa));
25747 	if (!pmksa) {
25748 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
25749 		return QDF_STATUS_E_NOMEM;
25750 	}
25751 
25752 	if (!pmk_cache->ssid_len) {
25753 		qdf_copy_macaddr(&pmksa->bssid, &pmk_cache->bssid);
25754 	} else {
25755 		qdf_mem_copy(pmksa->ssid, pmk_cache->ssid, pmk_cache->ssid_len);
25756 		qdf_mem_copy(pmksa->cache_id, pmk_cache->cache_id,
25757 			     WLAN_CACHE_ID_LEN);
25758 		pmksa->ssid_len = pmk_cache->ssid_len;
25759 	}
25760 	qdf_mem_copy(pmksa->pmkid, pmk_cache->pmkid, PMKID_LEN);
25761 	qdf_mem_copy(pmksa->pmk, pmk_cache->pmk, pmk_cache->pmk_len);
25762 	pmksa->pmk_len = pmk_cache->pmk_len;
25763 	pmksa->pmk_entry_ts = qdf_get_system_timestamp();
25764 	pmksa->pmk_lifetime = pmk_cache->pmk_lifetime;
25765 	pmksa->pmk_lifetime_threshold = pmk_cache->pmk_lifetime_threshold;
25766 
25767 	result = wlan_crypto_set_del_pmksa(vdev, pmksa, true);
25768 	if (result != QDF_STATUS_SUCCESS) {
25769 		qdf_mem_zero(pmksa, sizeof(*pmksa));
25770 		qdf_mem_free(pmksa);
25771 	}
25772 
25773 	if (result == QDF_STATUS_SUCCESS && pmk_cache->pmk_len) {
25774 		sme_roam_set_psk_pmk(mac_handle, pmksa,
25775 				     adapter->deflink->vdev_id, false);
25776 		sme_set_pmk_cache_ft(mac_handle, adapter->deflink->vdev_id,
25777 				     pmk_cache);
25778 	}
25779 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
25780 
25781 	return result;
25782 }
25783 
25784 static QDF_STATUS wlan_hdd_del_pmksa_cache(struct hdd_adapter *adapter,
25785 					   struct wlan_crypto_pmksa *pmk_cache)
25786 {
25787 	QDF_STATUS result;
25788 	struct wlan_crypto_pmksa pmksa;
25789 	struct wlan_objmgr_vdev *vdev;
25790 
25791 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
25792 	if (!vdev)
25793 		return QDF_STATUS_E_FAILURE;
25794 
25795 	qdf_mem_zero(&pmksa, sizeof(pmksa));
25796 	if (!pmk_cache->ssid_len) {
25797 		qdf_copy_macaddr(&pmksa.bssid, &pmk_cache->bssid);
25798 	} else {
25799 		qdf_mem_copy(pmksa.ssid, pmk_cache->ssid, pmk_cache->ssid_len);
25800 		qdf_mem_copy(pmksa.cache_id, pmk_cache->cache_id,
25801 			     WLAN_CACHE_ID_LEN);
25802 		pmksa.ssid_len = pmk_cache->ssid_len;
25803 	}
25804 
25805 	result = wlan_crypto_set_del_pmksa(vdev, &pmksa, false);
25806 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
25807 
25808 	return result;
25809 }
25810 
25811 QDF_STATUS wlan_hdd_flush_pmksa_cache(struct wlan_hdd_link_info *link_info)
25812 {
25813 	QDF_STATUS result;
25814 	struct wlan_objmgr_vdev *vdev;
25815 
25816 	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_ID);
25817 	if (!vdev)
25818 		return QDF_STATUS_E_FAILURE;
25819 
25820 	result = wlan_crypto_set_del_pmksa(vdev, NULL, false);
25821 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
25822 
25823 	if (QDF_IS_STATUS_ERROR(result))
25824 		hdd_debug("Cannot flush PMKIDCache");
25825 
25826 	return result;
25827 }
25828 
25829 #if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
25830 	 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
25831 /*
25832  * wlan_hdd_is_pmksa_valid: API to validate pmksa
25833  * @pmksa: pointer to cfg80211_pmksa structure
25834  *
25835  * Return: True if valid else false
25836  */
25837 static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
25838 {
25839 	if (!pmksa->bssid) {
25840 		hdd_warn("bssid is NULL");
25841 		if (!pmksa->ssid || !pmksa->cache_id) {
25842 			hdd_err("either ssid or cache_id are NULL");
25843 			return false;
25844 		}
25845 	}
25846 	return true;
25847 }
25848 
25849 /*
25850  * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
25851  * @adapter: Pointer to hdd adapter
25852  * @pmk_cache: pmk that needs to be updated
25853  * @pmksa: pmk from supplicant
25854  * @is_delete: Bool to decide set or delete PMK
25855  * Return: None
25856  */
25857 static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
25858 				struct wlan_crypto_pmksa *pmk_cache,
25859 				struct cfg80211_pmksa *pmksa, bool is_delete)
25860 {
25861 	if (pmksa->bssid) {
25862 		hdd_debug("%s PMKSA for " QDF_MAC_ADDR_FMT,
25863 			  is_delete ? "Delete" : "Set",
25864 			  QDF_MAC_ADDR_REF(pmksa->bssid));
25865 		qdf_mem_copy(pmk_cache->bssid.bytes,
25866 			     pmksa->bssid, QDF_MAC_ADDR_SIZE);
25867 	} else {
25868 		qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, pmksa->ssid_len);
25869 		qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
25870 			     CACHE_ID_LEN);
25871 		pmk_cache->ssid_len = pmksa->ssid_len;
25872 		hdd_debug("%s PMKSA for ssid " QDF_SSID_FMT " cache_id %x %x",
25873 			  is_delete ? "Delete" : "Set",
25874 			  QDF_SSID_REF(pmk_cache->ssid_len, pmk_cache->ssid),
25875 			  pmk_cache->cache_id[0],
25876 			  pmk_cache->cache_id[1]);
25877 	}
25878 	qdf_mem_copy(pmk_cache->pmkid, pmksa->pmkid, PMKID_LEN);
25879 
25880 	hdd_fill_pmksa_lifetime(pmksa, pmk_cache);
25881 
25882 	if (is_delete)
25883 		return;
25884 
25885 	if (pmksa->pmk_len && (pmksa->pmk_len <= MAX_PMK_LEN)) {
25886 		qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
25887 		pmk_cache->pmk_len = pmksa->pmk_len;
25888 	} else
25889 		hdd_err("Invalid pmk len is %zu", pmksa->pmk_len);
25890 }
25891 #else
25892 /*
25893  * wlan_hdd_is_pmksa_valid: API to validate pmksa
25894  * @pmksa: pointer to cfg80211_pmksa structure
25895  *
25896  * Return: True if valid else false
25897  */
25898 static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
25899 {
25900 	if (!pmksa->bssid) {
25901 		hdd_err("both bssid is NULL %pK", pmksa->bssid);
25902 		return false;
25903 	}
25904 	return true;
25905 }
25906 
25907 /*
25908  * hdd_fill_pmksa_info: API to update struct wlan_crypto_pmksa from
25909  * cfg80211_pmksa
25910  * @adapter: Pointer to hdd adapter
25911  * @pmk_cache: pmk which needs to be updated
25912  * @pmksa: pmk from supplicant
25913  * @is_delete: Bool to decide whether to set or delete PMK
25914  *
25915  * Return: None
25916  */
25917 static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
25918 				struct wlan_crypto_pmksa *pmk_cache,
25919 				struct cfg80211_pmksa *pmksa, bool is_delete)
25920 {
25921 	mac_handle_t mac_handle;
25922 
25923 	hdd_debug("%s PMKSA for " QDF_MAC_ADDR_FMT, is_delete ? "Delete" : "Set",
25924 		  QDF_MAC_ADDR_REF(pmksa->bssid));
25925 	qdf_mem_copy(pmk_cache->bssid.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
25926 
25927 	if (is_delete)
25928 		return;
25929 	mac_handle = hdd_adapter_get_mac_handle(adapter);
25930 	sme_get_pmk_info(mac_handle, adapter->deflink->vdev_id, pmk_cache);
25931 	qdf_mem_copy(pmk_cache->pmkid, pmksa->pmkid, PMKID_LEN);
25932 }
25933 #endif
25934 
25935 /**
25936  * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
25937  * @wiphy: Pointer to wiphy
25938  * @dev: Pointer to network device
25939  * @pmksa: Pointer to set pmksa parameter
25940  *
25941  * Return: 0 for success, non-zero for failure
25942  */
25943 static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
25944 					 struct net_device *dev,
25945 					 struct cfg80211_pmksa *pmksa)
25946 {
25947 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
25948 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
25949 	QDF_STATUS result = QDF_STATUS_SUCCESS;
25950 	int status;
25951 	struct wlan_crypto_pmksa *pmk_cache;
25952 
25953 	hdd_enter();
25954 
25955 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
25956 		hdd_err("Command not allowed in FTM mode");
25957 		return -EINVAL;
25958 	}
25959 
25960 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
25961 		return -EINVAL;
25962 
25963 	if (!pmksa) {
25964 		hdd_err("pmksa is NULL");
25965 		return -EINVAL;
25966 	}
25967 
25968 	if (!pmksa->pmkid) {
25969 		hdd_err("pmksa->pmkid(%pK) is NULL",
25970 		       pmksa->pmkid);
25971 		return -EINVAL;
25972 	}
25973 
25974 	if (!wlan_hdd_is_pmksa_valid(pmksa))
25975 		return -EINVAL;
25976 
25977 	status = wlan_hdd_validate_context(hdd_ctx);
25978 
25979 	if (0 != status)
25980 		return status;
25981 
25982 	pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
25983 	if (!pmk_cache)
25984 		return -ENOMEM;
25985 
25986 	hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, false);
25987 
25988 	/*
25989 	 * Add to the PMKSA Cache in CSR
25990 	 * PMKSA cache will be having following
25991 	 * 1. pmkid id
25992 	 * 2. pmk
25993 	 * 3. bssid or cache identifier
25994 	 */
25995 	result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
25996 
25997 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
25998 		   TRACE_CODE_HDD_CFG80211_SET_PMKSA,
25999 		   adapter->deflink->vdev_id, result);
26000 
26001 	if (QDF_IS_STATUS_SUCCESS(result) || result == QDF_STATUS_E_EXISTS)
26002 		sme_set_del_pmkid_cache(hdd_ctx->psoc,
26003 					adapter->deflink->vdev_id,
26004 					pmk_cache, true);
26005 
26006 	qdf_mem_zero(pmk_cache, sizeof(*pmk_cache));
26007 
26008 	qdf_mem_free(pmk_cache);
26009 	hdd_exit();
26010 
26011 	return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
26012 }
26013 
26014 /**
26015  * wlan_hdd_cfg80211_set_pmksa() - set pmksa
26016  * @wiphy: Pointer to wiphy
26017  * @dev: Pointer to network device
26018  * @pmksa: Pointer to set pmksa parameter
26019  *
26020  * Return: 0 for success, non-zero for failure
26021  */
26022 static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
26023 				       struct net_device *dev,
26024 				       struct cfg80211_pmksa *pmksa)
26025 {
26026 	int errno;
26027 	struct osif_vdev_sync *vdev_sync;
26028 
26029 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26030 	if (errno)
26031 		return errno;
26032 
26033 	errno = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
26034 
26035 	osif_vdev_sync_op_stop(vdev_sync);
26036 
26037 	return errno;
26038 }
26039 
26040 /**
26041  * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
26042  * @wiphy: Pointer to wiphy
26043  * @dev: Pointer to network device
26044  * @pmksa: Pointer to pmksa parameter
26045  *
26046  * Return: 0 for success, non-zero for failure
26047  */
26048 static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
26049 					 struct net_device *dev,
26050 					 struct cfg80211_pmksa *pmksa)
26051 {
26052 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26053 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26054 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
26055 	int status = 0;
26056 	struct wlan_crypto_pmksa *pmk_cache;
26057 
26058 	hdd_enter();
26059 
26060 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26061 		hdd_err("Command not allowed in FTM mode");
26062 		return -EINVAL;
26063 	}
26064 
26065 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26066 		return -EINVAL;
26067 
26068 	if (!pmksa) {
26069 		hdd_err("pmksa is NULL");
26070 		return -EINVAL;
26071 	}
26072 
26073 	if (!wlan_hdd_is_pmksa_valid(pmksa))
26074 		return -EINVAL;
26075 
26076 	status = wlan_hdd_validate_context(hdd_ctx);
26077 
26078 	if (0 != status)
26079 		return status;
26080 
26081 	pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
26082 	if (!pmk_cache)
26083 		return -ENOMEM;
26084 
26085 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26086 		   TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
26087 		   adapter->deflink->vdev_id, 0);
26088 
26089 	hdd_fill_pmksa_info(adapter, pmk_cache, pmksa, true);
26090 
26091 	qdf_status = wlan_hdd_del_pmksa_cache(adapter, pmk_cache);
26092 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
26093 		if (!pmksa->bssid)
26094 			hdd_err("Failed to delete PMKSA for null bssid");
26095 		else
26096 			hdd_err("Failed to delete PMKSA for " QDF_MAC_ADDR_FMT,
26097 				QDF_MAC_ADDR_REF(pmksa->bssid));
26098 		status = -EINVAL;
26099 	} else {
26100 		/* clear single_pmk_info information */
26101 		sme_clear_sae_single_pmk_info(hdd_ctx->psoc,
26102 					      adapter->deflink->vdev_id,
26103 					      pmk_cache);
26104 
26105 		/* Send the delete pmkid command to firmware */
26106 		sme_set_del_pmkid_cache(hdd_ctx->psoc,
26107 					adapter->deflink->vdev_id,
26108 					pmk_cache, false);
26109 	}
26110 
26111 	qdf_mem_zero(pmk_cache, sizeof(*pmk_cache));
26112 	qdf_mem_free(pmk_cache);
26113 
26114 	hdd_exit();
26115 
26116 	return status;
26117 }
26118 
26119 /**
26120  * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
26121  * @wiphy: Pointer to wiphy
26122  * @dev: Pointer to network device
26123  * @pmksa: Pointer to pmksa parameter
26124  *
26125  * Return: 0 for success, non-zero for failure
26126  */
26127 static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
26128 				       struct net_device *dev,
26129 				       struct cfg80211_pmksa *pmksa)
26130 {
26131 	int errno;
26132 	struct osif_vdev_sync *vdev_sync;
26133 
26134 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26135 	if (errno)
26136 		return errno;
26137 
26138 	errno = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
26139 
26140 	osif_vdev_sync_op_stop(vdev_sync);
26141 
26142 	return errno;
26143 
26144 }
26145 
26146 /**
26147  * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
26148  * @wiphy: Pointer to wiphy
26149  * @dev: Pointer to network device
26150  *
26151  * Return: 0 for success, non-zero for failure
26152  */
26153 static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
26154 					   struct net_device *dev)
26155 {
26156 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26157 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26158 	int errno;
26159 	QDF_STATUS status;
26160 
26161 	hdd_enter();
26162 
26163 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26164 		hdd_err("Command not allowed in FTM mode");
26165 		return -EINVAL;
26166 	}
26167 
26168 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26169 		return -EINVAL;
26170 
26171 	hdd_debug("Flushing PMKSA");
26172 
26173 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26174 	errno  = wlan_hdd_validate_context(hdd_ctx);
26175 	if (errno)
26176 		return errno;
26177 
26178 	status = wlan_hdd_flush_pmksa_cache(adapter->deflink);
26179 	if (status == QDF_STATUS_E_NOSUPPORT)
26180 		errno = -EOPNOTSUPP;
26181 	else if (QDF_IS_STATUS_ERROR(status))
26182 		errno = -EINVAL;
26183 
26184 	sme_set_del_pmkid_cache(hdd_ctx->psoc, adapter->deflink->vdev_id,
26185 				NULL, false);
26186 	hdd_exit();
26187 	return errno;
26188 }
26189 
26190 /**
26191  * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
26192  * @wiphy: Pointer to wiphy
26193  * @dev: Pointer to network device
26194  *
26195  * Return: 0 for success, non-zero for failure
26196  */
26197 static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
26198 					 struct net_device *dev)
26199 {
26200 	int errno;
26201 	struct osif_vdev_sync *vdev_sync;
26202 
26203 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26204 	if (errno)
26205 		return errno;
26206 
26207 	errno = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
26208 
26209 	osif_vdev_sync_op_stop(vdev_sync);
26210 
26211 	return errno;
26212 }
26213 
26214 #if defined(KERNEL_SUPPORT_11R_CFG80211)
26215 /**
26216  * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
26217  * @wiphy: Pointer to wiphy
26218  * @dev: Pointer to network device
26219  * @ftie: Pointer to fast transition ie parameter
26220  *
26221  * Return: 0 for success, non-zero for failure
26222  */
26223 static int
26224 __wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
26225 				  struct net_device *dev,
26226 				  struct cfg80211_update_ft_ies_params *ftie)
26227 {
26228 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
26229 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26230 	int status;
26231 
26232 	hdd_enter();
26233 
26234 	status = wlan_hdd_validate_context(hdd_ctx);
26235 	if (status)
26236 		return status;
26237 
26238 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26239 		hdd_err("Command not allowed in FTM mode");
26240 		return -EINVAL;
26241 	}
26242 
26243 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26244 		return -EINVAL;
26245 
26246 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26247 		   TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
26248 		   adapter->deflink->vdev_id, 0);
26249 
26250 	/* Added for debug on reception of Re-assoc Req. */
26251 	if (!hdd_cm_is_vdev_associated(adapter->deflink)) {
26252 		hdd_err("Called with Ie of length = %zu when not associated",
26253 		       ftie->ie_len);
26254 		hdd_err("Should be Re-assoc Req IEs");
26255 	}
26256 	hdd_debug("called with Ie of length = %zu", ftie->ie_len);
26257 
26258 	ucfg_cm_set_ft_ies(hdd_ctx->pdev, adapter->deflink->vdev_id,
26259 			   (const u8 *)ftie->ie, ftie->ie_len);
26260 	hdd_exit();
26261 	return 0;
26262 }
26263 
26264 /**
26265  * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
26266  * @wiphy: Pointer to wiphy
26267  * @dev: Pointer to network device
26268  * @ftie: Pointer to fast transition ie parameter
26269  *
26270  * Return: 0 for success, non-zero for failure
26271  */
26272 static int
26273 wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
26274 				struct net_device *dev,
26275 				struct cfg80211_update_ft_ies_params *ftie)
26276 {
26277 	int errno;
26278 	struct osif_vdev_sync *vdev_sync;
26279 
26280 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26281 	if (errno)
26282 		return errno;
26283 
26284 	errno = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
26285 
26286 	osif_vdev_sync_op_stop(vdev_sync);
26287 
26288 	return errno;
26289 }
26290 #endif
26291 
26292 #if defined(CFG80211_EXTERNAL_DH_UPDATE_SUPPORT) || \
26293 (LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0))
26294 /**
26295  * __wlan_hdd_cfg80211_update_owe_info() - update OWE info
26296  * @wiphy: Pointer to wiphy
26297  * @dev: Pointer to network device
26298  * @owe_info: Pointer to OWE info
26299  *
26300  * Return: 0 for success, non-zero for failure
26301  */
26302 static int
26303 __wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
26304 				    struct net_device *dev,
26305 				    struct cfg80211_update_owe_info *owe_info)
26306 {
26307 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
26308 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26309 	QDF_STATUS status;
26310 	int errno;
26311 	struct sap_context *sap_ctx;
26312 
26313 	hdd_enter_dev(dev);
26314 
26315 	errno = wlan_hdd_validate_context(hdd_ctx);
26316 	if (errno)
26317 		return errno;
26318 
26319 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26320 		hdd_err("Command not allowed in FTM mode");
26321 		return -EINVAL;
26322 	}
26323 
26324 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26325 		return -EINVAL;
26326 
26327 	hdd_debug("owe_status %d", owe_info->status);
26328 
26329 	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink);
26330 	status = wlansap_update_owe_info(sap_ctx, owe_info->peer, owe_info->ie,
26331 					 owe_info->ie_len, owe_info->status);
26332 	if (QDF_IS_STATUS_ERROR(status)) {
26333 		hdd_err("Failed to update OWE info");
26334 		errno = qdf_status_to_os_return(status);
26335 	}
26336 
26337 	hdd_exit();
26338 	return errno;
26339 }
26340 
26341 /**
26342  * wlan_hdd_cfg80211_update_owe_info() - update OWE info
26343  * @wiphy: Pointer to wiphy
26344  * @net_dev: Pointer to network device
26345  * @owe_info: Pointer to OWE info
26346  *
26347  * Return: 0 for success, non-zero for failure
26348  */
26349 static int
26350 wlan_hdd_cfg80211_update_owe_info(struct wiphy *wiphy,
26351 				  struct net_device *net_dev,
26352 				  struct cfg80211_update_owe_info *owe_info)
26353 {
26354 	struct osif_vdev_sync *vdev_sync;
26355 	int errno;
26356 
26357 	errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
26358 	if (errno)
26359 		return errno;
26360 
26361 	errno = __wlan_hdd_cfg80211_update_owe_info(wiphy, net_dev, owe_info);
26362 
26363 	osif_vdev_sync_op_stop(vdev_sync);
26364 
26365 	return errno;
26366 }
26367 #endif
26368 
26369 void wlan_hdd_cfg80211_update_replay_counter_cb(
26370 		void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
26371 
26372 {
26373 	struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
26374 	uint8_t temp_replay_counter[8];
26375 	int i;
26376 	uint8_t *p;
26377 
26378 	hdd_enter();
26379 
26380 	if (!adapter) {
26381 		hdd_err("HDD adapter is Null");
26382 		goto out;
26383 	}
26384 
26385 	if (!gtk_rsp_param) {
26386 		hdd_err("gtk_rsp_param is Null");
26387 		goto out;
26388 	}
26389 
26390 	if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
26391 		hdd_err("wlan Failed to get replay counter value");
26392 		goto out;
26393 	}
26394 
26395 	hdd_debug("updated replay counter: %llu from fwr",
26396 		gtk_rsp_param->replay_counter);
26397 	/* convert little to big endian since supplicant works on big endian */
26398 	p = (uint8_t *)&gtk_rsp_param->replay_counter;
26399 	for (i = 0; i < 8; i++)
26400 		temp_replay_counter[7 - i] = (uint8_t) p[i];
26401 
26402 	hdd_debug("gtk_rsp_param bssid "QDF_MAC_ADDR_FMT,
26403 		  QDF_MAC_ADDR_REF(gtk_rsp_param->bssid.bytes));
26404 	/* Update replay counter to NL */
26405 	cfg80211_gtk_rekey_notify(adapter->dev,
26406 					gtk_rsp_param->bssid.bytes,
26407 					temp_replay_counter, GFP_KERNEL);
26408 out:
26409 	hdd_exit();
26410 
26411 }
26412 
26413 #ifdef WLAN_FEATURE_GTK_OFFLOAD
26414 /**
26415  * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
26416  * @gtk_req: Pointer to GTK request
26417  * @data: Pointer to rekey data
26418  *
26419  * Return: none
26420  */
26421 #if (defined(CFG80211_REKEY_DATA_KEK_LEN) || \
26422 	LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
26423 static
26424 void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
26425 			   struct cfg80211_gtk_rekey_data *data)
26426 {
26427 	qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
26428 	gtk_req->kek_len = data->kek_len;
26429 }
26430 #else
26431 static
26432 void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
26433 			   struct cfg80211_gtk_rekey_data *data)
26434 {
26435 	qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
26436 	gtk_req->kek_len = NL80211_KEK_LEN;
26437 }
26438 #endif
26439 
26440 /**
26441  * wlan_hdd_copy_gtk_kck - Copy the KCK from GTK rekey data to GTK request
26442  * @gtk_req: Pointer to GTK request
26443  * @data: Pointer to rekey data
26444  *
26445  * Return: None
26446  */
26447 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
26448 static
26449 void wlan_hdd_copy_gtk_kck(struct pmo_gtk_req *gtk_req,
26450 			   struct cfg80211_gtk_rekey_data *data)
26451 {
26452 	qdf_mem_copy(gtk_req->kck, data->kck, data->kck_len);
26453 	gtk_req->kck_len = data->kck_len;
26454 }
26455 #else
26456 static
26457 void wlan_hdd_copy_gtk_kck(struct pmo_gtk_req *gtk_req,
26458 			   struct cfg80211_gtk_rekey_data *data)
26459 {
26460 	qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
26461 	gtk_req->kck_len = NL80211_KCK_LEN;
26462 }
26463 #endif
26464 /**
26465  * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
26466  * @wiphy: Pointer to wiphy
26467  * @dev: Pointer to network device
26468  * @data: Pointer to rekey data
26469  *
26470  * This function is used to offload GTK rekeying job to the firmware.
26471  *
26472  * Return: 0 for success, non-zero for failure
26473  */
26474 static
26475 int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
26476 		struct net_device *dev,
26477 		struct cfg80211_gtk_rekey_data *data)
26478 {
26479 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26480 	int result, i;
26481 	struct pmo_gtk_req *gtk_req = NULL;
26482 	struct hdd_context *hdd_ctx =  WLAN_HDD_GET_CTX(adapter);
26483 	uint8_t *buf;
26484 	struct wlan_objmgr_vdev *vdev;
26485 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
26486 
26487 	hdd_enter();
26488 
26489 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26490 		hdd_err("Command not allowed in FTM mode");
26491 		result = -EINVAL;
26492 		goto out;
26493 	}
26494 
26495 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id)) {
26496 		result = -EINVAL;
26497 		goto out;
26498 	}
26499 
26500 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26501 		   TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
26502 		   adapter->deflink->vdev_id, adapter->device_mode);
26503 
26504 	result = wlan_hdd_validate_context(hdd_ctx);
26505 	if (0 != result)
26506 		goto out;
26507 
26508 	gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
26509 	if (!gtk_req) {
26510 		result = -ENOMEM;
26511 		goto out;
26512 	}
26513 
26514 	/* convert big to little endian since driver work on little endian */
26515 	buf = (uint8_t *)&gtk_req->replay_counter;
26516 	for (i = 0; i < 8; i++)
26517 		buf[7 - i] = data->replay_ctr[i];
26518 
26519 	hdd_debug("current replay counter: %llu in user space",
26520 		gtk_req->replay_counter);
26521 
26522 	wlan_hdd_copy_gtk_kek(gtk_req, data);
26523 	wlan_hdd_copy_gtk_kck(gtk_req, data);
26524 
26525 	gtk_req->is_fils_connection = hdd_is_fils_connection(hdd_ctx, adapter);
26526 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
26527 					   WLAN_OSIF_POWER_ID);
26528 	if (!vdev) {
26529 		result = -EINVAL;
26530 		goto out;
26531 	}
26532 	status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
26533 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_POWER_ID);
26534 	if (status != QDF_STATUS_SUCCESS) {
26535 		hdd_err("Failed to cache GTK Offload");
26536 		result = qdf_status_to_os_return(status);
26537 	}
26538 out:
26539 	if (gtk_req)
26540 		qdf_mem_free(gtk_req);
26541 	hdd_exit();
26542 
26543 	return result;
26544 }
26545 
26546 /**
26547  * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
26548  * @wiphy: Pointer to wiphy
26549  * @dev: Pointer to network device
26550  * @data: Pointer to rekey data
26551  *
26552  * This function is used to offload GTK rekeying job to the firmware.
26553  *
26554  * Return: 0 for success, non-zero for failure
26555  */
26556 static
26557 int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
26558 				     struct net_device *dev,
26559 				     struct cfg80211_gtk_rekey_data *data)
26560 {
26561 	int errno;
26562 	struct osif_vdev_sync *vdev_sync;
26563 
26564 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26565 	if (errno)
26566 		return errno;
26567 
26568 	errno = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
26569 
26570 	osif_vdev_sync_op_stop(vdev_sync);
26571 
26572 	return errno;
26573 }
26574 #endif /* WLAN_FEATURE_GTK_OFFLOAD */
26575 
26576 /**
26577  * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
26578  * @wiphy: Pointer to wiphy
26579  * @dev: Pointer to network device
26580  * @params: Pointer to access control parameter
26581  *
26582  * Return: 0 for success, non-zero for failure
26583  */
26584 static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
26585 					 struct net_device *dev,
26586 					 const struct cfg80211_acl_data *params)
26587 {
26588 	int i;
26589 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26590 	struct hdd_hostapd_state *hostapd_state;
26591 	struct sap_config *config;
26592 	struct hdd_context *hdd_ctx;
26593 	int status;
26594 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
26595 
26596 	hdd_enter();
26597 
26598 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26599 		hdd_err("Command not allowed in FTM mode");
26600 		return -EINVAL;
26601 	}
26602 
26603 	if (!params) {
26604 		hdd_err("params is Null");
26605 		return -EINVAL;
26606 	}
26607 
26608 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26609 	status = wlan_hdd_validate_context(hdd_ctx);
26610 
26611 	if (0 != status)
26612 		return status;
26613 
26614 	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
26615 
26616 	if (!hostapd_state) {
26617 		hdd_err("hostapd_state is Null");
26618 		return -EINVAL;
26619 	}
26620 
26621 	hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
26622 		params->n_acl_entries);
26623 
26624 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26625 		   TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
26626 		   adapter->deflink->vdev_id, adapter->device_mode);
26627 
26628 	if (QDF_SAP_MODE == adapter->device_mode) {
26629 		config = &adapter->deflink->session.ap.sap_config;
26630 
26631 		/* default value */
26632 		config->num_accept_mac = 0;
26633 		config->num_deny_mac = 0;
26634 
26635 		/**
26636 		 * access control policy
26637 		 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
26638 		 *   listed in hostapd.deny file.
26639 		 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
26640 		 *   listed in hostapd.accept file.
26641 		 */
26642 		if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
26643 			config->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
26644 		} else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
26645 			   params->acl_policy) {
26646 			config->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
26647 		} else {
26648 			hdd_warn("Acl Policy : %d is not supported",
26649 				params->acl_policy);
26650 			return -ENOTSUPP;
26651 		}
26652 
26653 		if (eSAP_DENY_UNLESS_ACCEPTED == config->SapMacaddr_acl) {
26654 			config->num_accept_mac = params->n_acl_entries;
26655 			for (i = 0; i < params->n_acl_entries; i++) {
26656 				hdd_debug("** Add ACL MAC entry %i in WhiletList :"
26657 					QDF_MAC_ADDR_FMT, i,
26658 					QDF_MAC_ADDR_REF(
26659 						params->mac_addrs[i].addr));
26660 
26661 				qdf_mem_copy(&config->accept_mac[i],
26662 					     params->mac_addrs[i].addr,
26663 					     QDF_MAC_ADDR_SIZE);
26664 			}
26665 		} else if (eSAP_ACCEPT_UNLESS_DENIED == config->SapMacaddr_acl) {
26666 			config->num_deny_mac = params->n_acl_entries;
26667 			for (i = 0; i < params->n_acl_entries; i++) {
26668 				hdd_debug("** Add ACL MAC entry %i in DenyList :"
26669 					QDF_MAC_ADDR_FMT, i,
26670 					QDF_MAC_ADDR_REF(
26671 						params->mac_addrs[i].addr));
26672 
26673 				qdf_mem_copy(&config->deny_mac[i],
26674 					     params->mac_addrs[i].addr,
26675 					     QDF_MAC_ADDR_SIZE);
26676 			}
26677 		}
26678 		qdf_status = wlansap_set_mac_acl(
26679 			WLAN_HDD_GET_SAP_CTX_PTR(adapter->deflink), config);
26680 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
26681 			hdd_err("SAP Set Mac Acl fail");
26682 			return -EINVAL;
26683 		}
26684 	} else {
26685 		hdd_debug("Invalid device_mode %s(%d)",
26686 			  qdf_opmode_str(adapter->device_mode),
26687 			  adapter->device_mode);
26688 		return -EINVAL;
26689 	}
26690 	hdd_exit();
26691 	return 0;
26692 }
26693 
26694 /**
26695  * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
26696  *				__wlan_hdd_cfg80211_set_mac_acl
26697  * @wiphy: pointer to wiphy structure
26698  * @dev: pointer to net_device
26699  * @params: pointer to cfg80211_acl_data
26700  *
26701  * Return; 0 on success, error number otherwise
26702  */
26703 static int
26704 wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
26705 			      struct net_device *dev,
26706 			      const struct cfg80211_acl_data *params)
26707 {
26708 	int errno;
26709 	struct osif_vdev_sync *vdev_sync;
26710 
26711 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
26712 	if (errno)
26713 		return errno;
26714 
26715 	errno = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
26716 
26717 	osif_vdev_sync_op_stop(vdev_sync);
26718 
26719 	return errno;
26720 }
26721 
26722 #ifdef WLAN_NL80211_TESTMODE
26723 #ifdef FEATURE_WLAN_LPHB
26724 /**
26725  * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
26726  * @hdd_ctx: Pointer to hdd context
26727  * @lphb_ind: Pointer to low power heart beat indication parameter
26728  *
26729  * Return: none
26730  */
26731 static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
26732 		struct pmo_lphb_rsp *lphb_ind)
26733 {
26734 	struct sk_buff *skb;
26735 
26736 	hdd_debug("LPHB indication arrived");
26737 
26738 	if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
26739 		return;
26740 
26741 	if (!lphb_ind) {
26742 		hdd_err("invalid argument lphbInd");
26743 		return;
26744 	}
26745 
26746 	skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
26747 			wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
26748 	if (!skb) {
26749 		hdd_err("LPHB timeout, NL buffer alloc fail");
26750 		return;
26751 	}
26752 
26753 	if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
26754 		hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
26755 		goto nla_put_failure;
26756 	}
26757 	if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
26758 		hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
26759 		goto nla_put_failure;
26760 	}
26761 	if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
26762 			lphb_ind)) {
26763 		hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
26764 		goto nla_put_failure;
26765 	}
26766 	cfg80211_testmode_event(skb, GFP_ATOMIC);
26767 	return;
26768 
26769 nla_put_failure:
26770 	hdd_err("NLA Put fail");
26771 	kfree_skb(skb);
26772 }
26773 #endif /* FEATURE_WLAN_LPHB */
26774 
26775 /**
26776  * __wlan_hdd_cfg80211_testmode() - test mode
26777  * @wiphy: Pointer to wiphy
26778  * @data: Data pointer
26779  * @len: Data length
26780  *
26781  * Return: 0 for success, non-zero for failure
26782  */
26783 static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
26784 					void *data, int len)
26785 {
26786 	struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
26787 	int err;
26788 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
26789 
26790 	hdd_enter();
26791 
26792 	err = wlan_hdd_validate_context(hdd_ctx);
26793 	if (err)
26794 		return err;
26795 
26796 	if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
26797 		hdd_err("Driver Modules are closed");
26798 		return -EINVAL;
26799 	}
26800 
26801 	err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
26802 				      len, wlan_hdd_tm_policy);
26803 	if (err) {
26804 		hdd_err("Testmode INV ATTR");
26805 		return err;
26806 	}
26807 
26808 	if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
26809 		hdd_err("Testmode INV CMD");
26810 		return -EINVAL;
26811 	}
26812 
26813 	qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
26814 		   TRACE_CODE_HDD_CFG80211_TESTMODE,
26815 		   NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
26816 
26817 	switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
26818 #ifdef FEATURE_WLAN_LPHB
26819 	/* Low Power Heartbeat configuration request */
26820 	case WLAN_HDD_TM_CMD_WLAN_HB:
26821 	{
26822 		int buf_len;
26823 		void *buf;
26824 		struct pmo_lphb_req *hb_params = NULL;
26825 		struct pmo_lphb_req *hb_params_temp = NULL;
26826 		QDF_STATUS status;
26827 
26828 		if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
26829 			hdd_err("Testmode INV DATA");
26830 			return -EINVAL;
26831 		}
26832 
26833 		buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
26834 		buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
26835 		if (buf_len < sizeof(*hb_params_temp)) {
26836 			hdd_err("Invalid buffer length for TM_ATTR_DATA");
26837 			return -EINVAL;
26838 		}
26839 
26840 		hb_params_temp = (struct pmo_lphb_req *) buf;
26841 		if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
26842 		    && (hb_params_temp->params.lphb_tcp_params.
26843 			time_period_sec == 0))
26844 			return -EINVAL;
26845 
26846 		if (buf_len > sizeof(*hb_params)) {
26847 			hdd_err("buf_len=%d exceeded hb_params size limit",
26848 				buf_len);
26849 			return -ERANGE;
26850 		}
26851 
26852 		hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
26853 				sizeof(*hb_params));
26854 		if (!hb_params)
26855 			return -ENOMEM;
26856 
26857 		qdf_mem_zero(hb_params, sizeof(*hb_params));
26858 		qdf_mem_copy(hb_params, buf, buf_len);
26859 		status = ucfg_pmo_lphb_config_req(
26860 					hdd_ctx->psoc,
26861 					hb_params, (void *)hdd_ctx,
26862 					wlan_hdd_cfg80211_lphb_ind_handler);
26863 		if (status != QDF_STATUS_SUCCESS)
26864 			hdd_err("LPHB Config Fail, disable");
26865 
26866 		qdf_mem_free(hb_params);
26867 		return 0;
26868 	}
26869 #endif /* FEATURE_WLAN_LPHB */
26870 
26871 #if  defined(QCA_WIFI_FTM)
26872 	case WLAN_HDD_TM_CMD_WLAN_FTM:
26873 	{
26874 		if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) {
26875 			hdd_err("FTM Command not allowed in mission mode, mode %d",
26876 				hdd_get_conparam());
26877 			return -EINVAL;
26878 		}
26879 
26880 		err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->pdev,
26881 						     data, len);
26882 		break;
26883 	}
26884 #endif
26885 	default:
26886 		hdd_err("command: %d not supported",
26887 			nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
26888 		return -EOPNOTSUPP;
26889 	}
26890 
26891 	hdd_exit();
26892 	return err;
26893 }
26894 
26895 /**
26896  * wlan_hdd_cfg80211_testmode() - test mode
26897  * @wiphy: Pointer to wiphy
26898  * @wdev: Pointer to wireless device
26899  * @data: Data pointer
26900  * @len: Data length
26901  *
26902  * Return: 0 for success, non-zero for failure
26903  */
26904 static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
26905 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
26906 				      struct wireless_dev *wdev,
26907 #endif
26908 				      void *data, int len)
26909 {
26910 	struct osif_psoc_sync *psoc_sync;
26911 	int errno;
26912 
26913 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
26914 	if (errno)
26915 		return errno;
26916 
26917 	errno = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
26918 
26919 	osif_psoc_sync_op_stop(psoc_sync);
26920 
26921 	return errno;
26922 }
26923 
26924 #endif /* CONFIG_NL80211_TESTMODE */
26925 
26926 #ifdef QCA_HT_2040_COEX
26927 /**
26928  * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
26929  * @wiphy: Pointer to wiphy
26930  * @dev: Pointer to network device
26931  * @chandef: Pointer to channel definition parameter
26932  *
26933  * Return: 0 for success, non-zero for failure
26934  */
26935 static int
26936 __wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
26937 					 struct net_device *dev,
26938 					 struct cfg80211_chan_def *chandef)
26939 {
26940 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
26941 	struct hdd_context *hdd_ctx;
26942 	QDF_STATUS status;
26943 	int retval = 0;
26944 	enum nl80211_channel_type channel_type;
26945 
26946 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
26947 		hdd_err("Command not allowed in FTM mode");
26948 		return -EINVAL;
26949 	}
26950 
26951 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
26952 		return -EINVAL;
26953 
26954 	if (!(adapter->device_mode == QDF_SAP_MODE ||
26955 	      adapter->device_mode == QDF_P2P_GO_MODE))
26956 		return -EOPNOTSUPP;
26957 
26958 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
26959 	status = wlan_hdd_validate_context(hdd_ctx);
26960 	if (status)
26961 		return status;
26962 
26963 	if (chandef->width < NL80211_CHAN_WIDTH_80)
26964 		channel_type = cfg80211_get_chandef_type(chandef);
26965 	else
26966 		channel_type = NL80211_CHAN_HT40PLUS;
26967 	hdd_debug("Channel width changed to %d ", channel_type);
26968 
26969 	/* Change SAP ht2040 mode */
26970 	status = hdd_set_sap_ht2040_mode(adapter, channel_type);
26971 	if (status != QDF_STATUS_SUCCESS) {
26972 		hdd_err("Cannot set SAP HT20/40 mode!");
26973 		retval = -EINVAL;
26974 	}
26975 
26976 	return retval;
26977 }
26978 
26979 /**
26980  * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
26981  * @wiphy: Pointer to wiphy
26982  * @dev: Pointer to network device
26983  * @link_id: Link id for which channel width has to be applied
26984  * @chandef: Pointer to channel definition parameter
26985  *
26986  * Return: 0 for success, non-zero for failure
26987  */
26988 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
26989 static int
26990 wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
26991 				       struct net_device *dev,
26992 				       unsigned int link_id,
26993 				       struct cfg80211_chan_def *chandef)
26994 #else
26995 static int
26996 wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
26997 				       struct net_device *dev,
26998 				       struct cfg80211_chan_def *chandef)
26999 #endif
27000 {
27001 	int errno;
27002 	struct osif_vdev_sync *vdev_sync;
27003 
27004 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27005 	if (errno)
27006 		return errno;
27007 
27008 	errno = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
27009 
27010 	osif_vdev_sync_op_stop(vdev_sync);
27011 
27012 	return errno;
27013 }
27014 #endif
27015 
27016 #ifdef CHANNEL_SWITCH_SUPPORTED
27017 /**
27018  * __wlan_hdd_cfg80211_channel_switch()- function to switch
27019  * channel in SAP/GO
27020  * @wiphy:  wiphy pointer
27021  * @dev: dev pointer.
27022  * @csa_params: Change channel params
27023  *
27024  * This function is called to switch channel in SAP/GO
27025  *
27026  * Return: 0 if success else return non zero
27027  */
27028 static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
27029 				struct net_device *dev,
27030 				struct cfg80211_csa_settings *csa_params)
27031 {
27032 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
27033 	struct hdd_context *hdd_ctx;
27034 	int ret;
27035 	enum phy_ch_width ch_width;
27036 	bool status;
27037 	struct hdd_hostapd_state *hostapd_state;
27038 
27039 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
27040 		return -EINVAL;
27041 
27042 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
27043 	ret = wlan_hdd_validate_context(hdd_ctx);
27044 
27045 	if (0 != ret)
27046 		return ret;
27047 
27048 	if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
27049 		(QDF_SAP_MODE != adapter->device_mode))
27050 		return -ENOTSUPP;
27051 
27052 	status = policy_mgr_is_sap_allowed_on_dfs_freq(
27053 					hdd_ctx->pdev,
27054 					adapter->deflink->vdev_id,
27055 					csa_params->chandef.chan->center_freq);
27056 	if (!status)
27057 		return -EINVAL;
27058 
27059 	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->deflink->vdev_id,
27060 				    CSA_REASON_USER_INITIATED);
27061 
27062 	ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
27063 	hdd_debug("Freq %d width %d ch_width %d",
27064 		  csa_params->chandef.chan->center_freq,
27065 		  csa_params->chandef.width, ch_width);
27066 	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
27067 	qdf_event_reset(&hostapd_state->qdf_event);
27068 
27069 	ret =
27070 	    hdd_softap_set_channel_change(dev,
27071 					  csa_params->chandef.chan->center_freq,
27072 					  ch_width, false);
27073 	if (ret) {
27074 		hdd_err("CSA failed to %d, ret %d",
27075 			csa_params->chandef.chan->center_freq, ret);
27076 		return ret;
27077 	}
27078 
27079 	status = qdf_wait_for_event_completion(&hostapd_state->qdf_event,
27080 					       SME_CMD_START_BSS_TIMEOUT);
27081 	if (QDF_IS_STATUS_ERROR(status))
27082 		hdd_err("wait for qdf_event failed!!");
27083 	else
27084 		hdd_debug("csa done");
27085 
27086 	return ret;
27087 }
27088 
27089 /**
27090  * wlan_hdd_cfg80211_channel_switch()- function to switch
27091  * channel in SAP/GO
27092  * @wiphy:  wiphy pointer
27093  * @dev: dev pointer.
27094  * @csa_params: Change channel params
27095  *
27096  * This function is called to switch channel in SAP/GO
27097  *
27098  * Return: 0 if success else return non zero
27099  */
27100 static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
27101 				struct net_device *dev,
27102 				struct cfg80211_csa_settings *csa_params)
27103 {
27104 	int errno;
27105 	struct osif_vdev_sync *vdev_sync;
27106 
27107 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27108 	if (errno)
27109 		return errno;
27110 
27111 	errno = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
27112 
27113 	osif_vdev_sync_op_stop(vdev_sync);
27114 
27115 	return errno;
27116 }
27117 #endif
27118 
27119 int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
27120 					   uint32_t chan_freq,
27121 					   enum policy_mgr_conn_update_reason reason)
27122 {
27123 	QDF_STATUS status;
27124 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
27125 
27126 	hdd_enter();
27127 
27128 	status = policy_mgr_reset_connection_update(hdd_ctx->psoc);
27129 	if (!QDF_IS_STATUS_SUCCESS(status))
27130 		hdd_err("clearing event failed");
27131 
27132 	status = policy_mgr_current_connections_update(
27133 			hdd_ctx->psoc, adapter->deflink->vdev_id,
27134 			chan_freq, reason, POLICY_MGR_DEF_REQ_ID);
27135 	switch (status) {
27136 	case QDF_STATUS_E_FAILURE:
27137 		/*
27138 		 * QDF_STATUS_E_FAILURE indicates that some error has occurred
27139 		 * while changing the hw mode
27140 		 */
27141 		hdd_err("ERROR: connections update failed!!");
27142 		return -EINVAL;
27143 
27144 	case QDF_STATUS_SUCCESS:
27145 		/*
27146 		 * QDF_STATUS_SUCCESS indicates that HW mode change has been
27147 		 * triggered and wait for it to finish.
27148 		 */
27149 		status = policy_mgr_wait_for_connection_update(
27150 						hdd_ctx->psoc);
27151 		if (!QDF_IS_STATUS_SUCCESS(status)) {
27152 			hdd_err("ERROR: qdf wait for event failed!!");
27153 			return -EINVAL;
27154 		}
27155 		if (QDF_MONITOR_MODE == adapter->device_mode)
27156 			hdd_info("Monitor mode:channel freq:%d (SMM->DBS)", chan_freq);
27157 		break;
27158 
27159 	default:
27160 		/*
27161 		 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
27162 		 * required, so caller can proceed further.
27163 		 */
27164 		break;
27165 
27166 	}
27167 	hdd_exit();
27168 
27169 	return 0;
27170 }
27171 
27172 #ifdef FEATURE_MONITOR_MODE_SUPPORT
27173 /**
27174  * __wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
27175  * @wiphy: Handle to struct wiphy to get handle to module context.
27176  * @chandef: Contains information about the capture channel to be set.
27177  *
27178  * This interface is called if and only if monitor mode interface alone is
27179  * active.
27180  *
27181  * Return: 0 success or error code on failure.
27182  */
27183 static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
27184 				       struct cfg80211_chan_def *chandef)
27185 {
27186 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
27187 	struct hdd_adapter *adapter;
27188 	struct hdd_station_ctx *sta_ctx;
27189 	struct hdd_mon_set_ch_info *ch_info;
27190 	QDF_STATUS status;
27191 	mac_handle_t mac_handle;
27192 	struct qdf_mac_addr bssid;
27193 	struct channel_change_req *req;
27194 	struct ch_params ch_params = {0};
27195 	int ret;
27196 	enum channel_state chan_freq_state;
27197 	uint8_t max_fw_bw;
27198 	enum phy_ch_width ch_width;
27199 	qdf_freq_t sec_ch_2g_freq = 0;
27200 
27201 	hdd_enter();
27202 
27203 	ret = wlan_hdd_validate_context(hdd_ctx);
27204 	if (ret)
27205 		return ret;
27206 
27207 	mac_handle = hdd_ctx->mac_handle;
27208 
27209 	adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
27210 	if (!adapter)
27211 		return -EIO;
27212 
27213 	hdd_debug("%s: set monitor mode freq %d",
27214 		  adapter->dev->name, chandef->chan->center_freq);
27215 
27216 	/* Verify channel state before accepting this request */
27217 	chan_freq_state =
27218 		wlan_reg_get_channel_state_for_pwrmode(
27219 						hdd_ctx->pdev,
27220 						chandef->chan->center_freq,
27221 						REG_CURRENT_PWR_MODE);
27222 	if (chan_freq_state == CHANNEL_STATE_DISABLE ||
27223 	    chan_freq_state == CHANNEL_STATE_INVALID) {
27224 		hdd_err("Invalid chan freq received for monitor mode aborting");
27225 		return -EINVAL;
27226 	}
27227 
27228 	/* Verify the BW before accepting this request */
27229 	ch_width = hdd_map_nl_chan_width(chandef->width);
27230 
27231 	if (ch_width > CH_WIDTH_10MHZ ||
27232 	   (!cds_is_sub_20_mhz_enabled() && ch_width > CH_WIDTH_160MHZ)) {
27233 		hdd_err("invalid BW received %d", ch_width);
27234 		return -EINVAL;
27235 	}
27236 
27237 	max_fw_bw = sme_get_vht_ch_width();
27238 
27239 	if ((ch_width == CH_WIDTH_160MHZ &&
27240 	    max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) ||
27241 	    (ch_width == CH_WIDTH_80P80MHZ &&
27242 	    max_fw_bw <= WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)) {
27243 		hdd_err("FW does not support this BW %d max BW supported %d",
27244 			ch_width, max_fw_bw);
27245 		return -EINVAL;
27246 	}
27247 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
27248 	ch_info = &sta_ctx->ch_info;
27249 
27250 	if (WLAN_REG_IS_24GHZ_CH_FREQ(chandef->chan->center_freq) &&
27251 	    chandef->width == NL80211_CHAN_WIDTH_40 &&
27252 	    chandef->center_freq1) {
27253 		if (chandef->center_freq1 > chandef->chan->center_freq)
27254 			sec_ch_2g_freq = chandef->chan->center_freq + 20;
27255 		else if (chandef->center_freq1 < chandef->chan->center_freq)
27256 			sec_ch_2g_freq = chandef->chan->center_freq - 20;
27257 	}
27258 	hdd_debug("set mon ch:width=%d, freq %d sec_ch_2g_freq=%d",
27259 		  chandef->width, chandef->chan->center_freq, sec_ch_2g_freq);
27260 	qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
27261 		     QDF_MAC_ADDR_SIZE);
27262 
27263 	ch_params.ch_width = ch_width;
27264 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
27265 						chandef->chan->center_freq,
27266 						sec_ch_2g_freq, &ch_params,
27267 						REG_CURRENT_PWR_MODE);
27268 	if (wlan_hdd_change_hw_mode_for_given_chnl(adapter,
27269 						   chandef->chan->center_freq,
27270 						   POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
27271 		hdd_err("Failed to change hw mode");
27272 		return -EINVAL;
27273 	}
27274 
27275 	if (adapter->monitor_mode_vdev_up_in_progress) {
27276 		hdd_err_rl("monitor mode vdev up in progress");
27277 		return -EBUSY;
27278 	}
27279 
27280 	status = qdf_event_reset(&adapter->qdf_monitor_mode_vdev_up_event);
27281 	if (QDF_IS_STATUS_ERROR(status)) {
27282 		hdd_err_rl("failed to reinit monitor mode vdev up event");
27283 		return qdf_status_to_os_return(status);
27284 	}
27285 	adapter->monitor_mode_vdev_up_in_progress = true;
27286 
27287 	qdf_mem_zero(&ch_params, sizeof(struct ch_params));
27288 
27289 	req = qdf_mem_malloc(sizeof(struct channel_change_req));
27290 	if (!req)
27291 		return -ENOMEM;
27292 
27293 	req->vdev_id = adapter->deflink->vdev_id;
27294 	req->target_chan_freq = chandef->chan->center_freq;
27295 	req->ch_width = ch_width;
27296 
27297 	ch_params.ch_width = ch_width;
27298 	hdd_select_cbmode(adapter, chandef->chan->center_freq, sec_ch_2g_freq,
27299 			  &ch_params);
27300 
27301 	req->sec_ch_offset = ch_params.sec_ch_offset;
27302 	req->center_freq_seg0 = ch_params.center_freq_seg0;
27303 	req->center_freq_seg1 = ch_params.center_freq_seg1;
27304 
27305 	sme_fill_channel_change_request(mac_handle, req, ch_info->phy_mode);
27306 	status = sme_send_channel_change_req(mac_handle, req);
27307 	qdf_mem_free(req);
27308 
27309 	if (status) {
27310 		hdd_err_rl("Failed to set sme_RoamChannel for monitor mode status: %d",
27311 			   status);
27312 		adapter->monitor_mode_vdev_up_in_progress = false;
27313 		ret = qdf_status_to_os_return(status);
27314 		return ret;
27315 	}
27316 
27317 	/* block on a completion variable until vdev up success*/
27318 	status = qdf_wait_for_event_completion(
27319 				       &adapter->qdf_monitor_mode_vdev_up_event,
27320 					WLAN_MONITOR_MODE_VDEV_UP_EVT);
27321 	if (QDF_IS_STATUS_ERROR(status)) {
27322 		hdd_err_rl("monitor vdev up event time out vdev id: %d",
27323 			  adapter->deflink->vdev_id);
27324 		if (adapter->qdf_monitor_mode_vdev_up_event.force_set)
27325 			/*
27326 			 * SSR/PDR has caused shutdown, which has
27327 			 * forcefully set the event.
27328 			 */
27329 			hdd_err_rl("monitor mode vdev up event forcefully set");
27330 		else if (status == QDF_STATUS_E_TIMEOUT)
27331 			hdd_err_rl("monitor mode vdev up timed out");
27332 		else
27333 			hdd_err_rl("Failed monitor mode vdev up(status-%d)",
27334 				  status);
27335 
27336 		adapter->monitor_mode_vdev_up_in_progress = false;
27337 		return qdf_status_to_os_return(status);
27338 	}
27339 
27340 	hdd_exit();
27341 
27342 	return 0;
27343 }
27344 
27345 /**
27346  * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
27347  * @wiphy: Handle to struct wiphy to get handle to module context.
27348  * @chandef: Contains information about the capture channel to be set.
27349  *
27350  * This interface is called if and only if monitor mode interface alone is
27351  * active.
27352  *
27353  * Return: 0 success or error code on failure.
27354  */
27355 static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
27356 				       struct cfg80211_chan_def *chandef)
27357 {
27358 	struct osif_psoc_sync *psoc_sync;
27359 	int errno;
27360 
27361 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
27362 	if (errno)
27363 		return errno;
27364 
27365 	errno = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
27366 
27367 	osif_psoc_sync_op_stop(psoc_sync);
27368 
27369 	return errno;
27370 }
27371 #endif
27372 
27373 #define CNT_DIFF(cur, prev) \
27374 	((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
27375 #define MAX_COUNT 0xffffffff
27376 static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
27377 			struct scan_chan_info *chan,
27378 			struct scan_chan_info *info, uint32_t cmd_flag)
27379 {
27380 	if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
27381 	   (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
27382 		hdd_err("cmd flag is invalid: %d", info->cmd_flag);
27383 
27384 	mutex_lock(&hdd_ctx->chan_info_lock);
27385 
27386 	if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
27387 		qdf_mem_zero(chan, sizeof(*chan));
27388 
27389 	chan->freq = info->freq;
27390 	chan->noise_floor = info->noise_floor;
27391 	chan->clock_freq = info->clock_freq;
27392 	chan->cmd_flag = info->cmd_flag;
27393 	chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
27394 
27395 	chan->rx_clear_count =
27396 			CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
27397 
27398 	chan->tx_frame_count =
27399 			CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
27400 
27401 	mutex_unlock(&hdd_ctx->chan_info_lock);
27402 
27403 }
27404 #undef CNT_DIFF
27405 #undef MAX_COUNT
27406 
27407 #ifndef UPDATE_ASSOC_IE
27408 #define UPDATE_ASSOC_IE BIT(0)
27409 #endif
27410 
27411 #ifndef UPDATE_FILS_ERP_INFO
27412 #define UPDATE_FILS_ERP_INFO BIT(1)
27413 #endif
27414 
27415 #ifndef UPDATE_FILS_AUTH_TYPE
27416 #define UPDATE_FILS_AUTH_TYPE BIT(2)
27417 #endif
27418 
27419 #if defined(WLAN_FEATURE_FILS_SK) &&\
27420 	(defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) ||\
27421 		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))) &&\
27422 	(defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
27423 		(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
27424 static inline int
27425 hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
27426 				    struct hdd_context *hdd_ctx,
27427 				    struct cfg80211_connect_params *req,
27428 				    uint32_t changed)
27429 {
27430 	uint8_t *buf;
27431 	QDF_STATUS status;
27432 	enum wlan_fils_auth_type auth_type;
27433 	struct wlan_fils_con_info *fils_info;
27434 	int ret = 0;
27435 
27436 	fils_info = qdf_mem_malloc(sizeof(*fils_info));
27437 	if (!fils_info)
27438 		return -EINVAL;
27439 
27440 	fils_info->is_fils_connection = true;
27441 	if (changed & UPDATE_FILS_ERP_INFO) {
27442 		fils_info->username_len = req->fils_erp_username_len +
27443 					    sizeof(char) +
27444 					    req->fils_erp_realm_len;
27445 		if (fils_info->username_len >
27446 		    WLAN_CM_FILS_MAX_KEYNAME_NAI_LENGTH) {
27447 			hdd_err("Key NAI Length %d",
27448 				fils_info->username_len);
27449 			ret = -EINVAL;
27450 			goto free_mem;
27451 		}
27452 		if (req->fils_erp_username_len && req->fils_erp_username) {
27453 			buf = fils_info->username;
27454 			qdf_mem_copy(buf, req->fils_erp_username,
27455 				     req->fils_erp_username_len);
27456 			buf += req->fils_erp_username_len;
27457 			*buf++ = '@';
27458 			qdf_mem_copy(buf, req->fils_erp_realm,
27459 				     req->fils_erp_realm_len);
27460 		}
27461 
27462 		fils_info->next_seq_num = req->fils_erp_next_seq_num + 1;
27463 		fils_info->rrk_len = req->fils_erp_rrk_len;
27464 
27465 		if (fils_info->rrk_len > WLAN_CM_FILS_MAX_RRK_LENGTH) {
27466 			hdd_err("r_rk_length is invalid %d",
27467 				fils_info->rrk_len);
27468 			ret = -EINVAL;
27469 			goto free_mem;
27470 		}
27471 
27472 		if (req->fils_erp_rrk_len && req->fils_erp_rrk)
27473 			qdf_mem_copy(fils_info->rrk, req->fils_erp_rrk,
27474 				     fils_info->rrk_len);
27475 
27476 		fils_info->realm_len = req->fils_erp_realm_len;
27477 		if (fils_info->realm_len > WLAN_CM_FILS_MAX_REALM_LEN) {
27478 			hdd_err("Invalid fils realm len %d",
27479 				fils_info->realm_len);
27480 			ret = -EINVAL;
27481 			goto free_mem;
27482 		}
27483 		if (req->fils_erp_realm_len && req->fils_erp_realm)
27484 			qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
27485 				     fils_info->realm_len);
27486 	}
27487 
27488 	if (changed & UPDATE_FILS_AUTH_TYPE) {
27489 		auth_type = osif_cm_get_fils_auth_type(req->auth_type);
27490 		if (auth_type == FILS_PK_MAX) {
27491 			hdd_err("invalid auth type for fils %d",
27492 				req->auth_type);
27493 			ret = -EINVAL;
27494 			goto free_mem;
27495 		}
27496 
27497 		fils_info->auth_type = auth_type;
27498 	}
27499 
27500 	hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
27501 		  changed, fils_info->is_fils_connection,
27502 		  fils_info->username_len);
27503 	/*
27504 	 * Update the FILS config from adapter->roam_profile to
27505 	 * csr_session
27506 	 */
27507 	status = ucfg_cm_update_fils_config(hdd_ctx->psoc,
27508 					    adapter->deflink->vdev_id,
27509 					    fils_info);
27510 	if (QDF_IS_STATUS_ERROR(status))
27511 		hdd_err("Update FILS connect params failed %d", status);
27512 free_mem:
27513 	qdf_mem_free(fils_info);
27514 
27515 	return ret;
27516 }
27517 #else
27518 static inline int
27519 hdd_update_connect_params_fils_info(struct hdd_adapter *adapter,
27520 				    struct hdd_context *hdd_ctx,
27521 				    struct cfg80211_connect_params *req,
27522 				    uint32_t changed)
27523 {
27524 	return -EINVAL;
27525 }
27526 #endif
27527 
27528 #if defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
27529 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
27530 
27531 /**
27532  * __wlan_hdd_cfg80211_update_connect_params - update connect params
27533  * @wiphy: Handle to struct wiphy to get handle to module context.
27534  * @dev: Pointer to network device
27535  * @req: Pointer to connect params
27536  * @changed: Bitmap used to indicate the changed params
27537  *
27538  * Update the connect parameters while connected to a BSS. The updated
27539  * parameters can be used by driver/firmware for subsequent BSS selection
27540  * (roaming) decisions and to form the Authentication/(Re)Association
27541  * Request frames. This call does not request an immediate disassociation
27542  * or reassociation with the current BSS, i.e., this impacts only
27543  * subsequent (re)associations. The bits in changed are defined in enum
27544  * cfg80211_connect_params_changed
27545  *
27546  * Return: zero for success, non-zero for failure
27547  */
27548 static int
27549 __wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
27550 					  struct net_device *dev,
27551 					  struct cfg80211_connect_params *req,
27552 					  uint32_t changed)
27553 {
27554 	int ret;
27555 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
27556 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
27557 	QDF_STATUS status;
27558 	mac_handle_t mac_handle;
27559 	struct element_info assoc_ie;
27560 
27561 	hdd_enter_dev(dev);
27562 
27563 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
27564 		return -EINVAL;
27565 
27566 	ret = wlan_hdd_validate_context(hdd_ctx);
27567 	if (ret)
27568 		return -EINVAL;
27569 
27570 	mac_handle = hdd_ctx->mac_handle;
27571 
27572 	if (changed & UPDATE_ASSOC_IE) {
27573 		assoc_ie.len = req->ie_len;
27574 		assoc_ie.ptr = (uint8_t *)req->ie;
27575 		/*
27576 		 * Update this assoc IE received from user space to
27577 		 * umac. RSO command will pick up the assoc
27578 		 * IEs to be sent to firmware from the umac.
27579 		 */
27580 		ucfg_cm_update_session_assoc_ie(hdd_ctx->psoc,
27581 						adapter->deflink->vdev_id,
27582 						&assoc_ie);
27583 	}
27584 
27585 	if ((changed & UPDATE_FILS_ERP_INFO) ||
27586 	    (changed & UPDATE_FILS_AUTH_TYPE)) {
27587 		ret = hdd_update_connect_params_fils_info(adapter, hdd_ctx,
27588 							  req, changed);
27589 		if (ret)
27590 			return -EINVAL;
27591 
27592 		if (!hdd_ctx->is_fils_roaming_supported) {
27593 			hdd_debug("FILS roaming support %d",
27594 				  hdd_ctx->is_fils_roaming_supported);
27595 			return 0;
27596 		}
27597 	}
27598 
27599 	if (changed) {
27600 		status = sme_send_rso_connect_params(mac_handle,
27601 						     adapter->deflink->vdev_id);
27602 		if (QDF_IS_STATUS_ERROR(status))
27603 			hdd_err("Update connect params to fw failed %d",
27604 				status);
27605 	}
27606 
27607 	return 0;
27608 }
27609 
27610 /**
27611  * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
27612  *                __wlan_hdd_cfg80211_update_connect_params
27613  * @wiphy: Pointer to wiphy structure
27614  * @dev: Pointer to net_device
27615  * @req: Pointer to connect params
27616  * @changed: flags used to indicate the changed params
27617  *
27618  * Return: zero for success, non-zero for failure
27619  */
27620 static int
27621 wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
27622 					struct net_device *dev,
27623 					struct cfg80211_connect_params *req,
27624 					uint32_t changed)
27625 {
27626 	int errno;
27627 	struct osif_vdev_sync *vdev_sync;
27628 
27629 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27630 	if (errno)
27631 		return errno;
27632 
27633 	errno = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
27634 							  req, changed);
27635 
27636 	osif_vdev_sync_op_stop(vdev_sync);
27637 
27638 	return errno;
27639 }
27640 #endif
27641 
27642 #if defined(WLAN_FEATURE_SAE) && \
27643 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
27644 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
27645 #if (defined(CFG80211_EXTERNAL_AUTH_AP_SUPPORT) || \
27646 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
27647 /**
27648  * wlan_hdd_extauth_cache_pmkid() - Extract and cache pmkid
27649  * @adapter: hdd vdev/net_device context
27650  * @mac_handle: Handle to the MAC
27651  * @params: Pointer to external auth params.
27652  *
27653  * Extract the PMKID and BSS from external auth params and add to the
27654  * PMKSA Cache in CSR.
27655  */
27656 static void
27657 wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
27658 			     mac_handle_t mac_handle,
27659 			     struct cfg80211_external_auth_params *params)
27660 {
27661 	struct wlan_crypto_pmksa *pmk_cache;
27662 	QDF_STATUS result;
27663 
27664 	if (params->pmkid) {
27665 		pmk_cache = qdf_mem_malloc(sizeof(*pmk_cache));
27666 		if (!pmk_cache)
27667 			return;
27668 
27669 		qdf_mem_copy(pmk_cache->bssid.bytes, params->bssid,
27670 			     QDF_MAC_ADDR_SIZE);
27671 		qdf_mem_copy(pmk_cache->pmkid, params->pmkid,
27672 			     PMKID_LEN);
27673 		result = wlan_hdd_set_pmksa_cache(adapter, pmk_cache);
27674 		if (!QDF_IS_STATUS_SUCCESS(result))
27675 			hdd_debug("external_auth: Failed to cache PMKID");
27676 
27677 		qdf_mem_free(pmk_cache);
27678 	}
27679 
27680 }
27681 
27682 /**
27683  * wlan_hdd_extauth_copy_pmkid() - Copy the pmkid received from the
27684  * external authentication command received from the userspace.
27685  * @params: pointer to auth params
27686  * @pmkid: Pointer to destination pmkid buffer to be filled
27687  *
27688  * The caller should ensure that destination pmkid buffer is not NULL.
27689  *
27690  * Return: None
27691  */
27692 static void
27693 wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
27694 			    uint8_t *pmkid)
27695 {
27696 	if (params->pmkid)
27697 		qdf_mem_copy(pmkid, params->pmkid, PMKID_LEN);
27698 }
27699 
27700 #else
27701 static void
27702 wlan_hdd_extauth_cache_pmkid(struct hdd_adapter *adapter,
27703 			     mac_handle_t mac_handle,
27704 			     struct cfg80211_external_auth_params *params)
27705 {}
27706 
27707 static void
27708 wlan_hdd_extauth_copy_pmkid(struct cfg80211_external_auth_params *params,
27709 			    uint8_t *pmkid)
27710 {}
27711 #endif
27712 /**
27713  * __wlan_hdd_cfg80211_external_auth() - Handle external auth
27714  *
27715  * @wiphy: Pointer to wireless phy
27716  * @dev: net device
27717  * @params: Pointer to external auth params.
27718  * Return: 0 on success, negative errno on failure
27719  *
27720  * Userspace sends status of the external authentication(e.g., SAE) with a peer.
27721  * The message carries BSSID of the peer and auth status (WLAN_STATUS_SUCCESS/
27722  * WLAN_STATUS_UNSPECIFIED_FAILURE) in params.
27723  * Userspace may send PMKID in params, which can be used for
27724  * further connections.
27725  */
27726 static int
27727 __wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
27728 				  struct net_device *dev,
27729 				  struct cfg80211_external_auth_params *params)
27730 {
27731 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
27732 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
27733 	int ret;
27734 	mac_handle_t mac_handle;
27735 	struct qdf_mac_addr peer_mac_addr;
27736 	uint8_t pmkid[PMKID_LEN] = {0};
27737 
27738 	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
27739 		hdd_err("Command not allowed in FTM mode");
27740 		return -EPERM;
27741 	}
27742 
27743 	if (wlan_hdd_validate_vdev_id(adapter->deflink->vdev_id))
27744 		return -EINVAL;
27745 
27746 	ret = wlan_hdd_validate_context(hdd_ctx);
27747 	if (ret)
27748 		return ret;
27749 
27750 	hdd_debug("external_auth status: %d peer mac: " QDF_MAC_ADDR_FMT,
27751 		  params->status, QDF_MAC_ADDR_REF(params->bssid));
27752 	mac_handle = hdd_ctx->mac_handle;
27753 	qdf_mem_copy(peer_mac_addr.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
27754 
27755 	wlan_hdd_extauth_cache_pmkid(adapter, mac_handle, params);
27756 
27757 	wlan_hdd_extauth_copy_pmkid(params, pmkid);
27758 	sme_handle_sae_msg(mac_handle, adapter->deflink->vdev_id,
27759 			   params->status, peer_mac_addr, pmkid);
27760 
27761 	return ret;
27762 }
27763 
27764 /**
27765  * wlan_hdd_cfg80211_external_auth() - Handle external auth
27766  * @wiphy: Pointer to wireless phy
27767  * @dev: net device
27768  * @params: Pointer to external auth params
27769  *
27770  * Return: 0 on success, negative errno on failure
27771  */
27772 static int
27773 wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
27774 				struct net_device *dev,
27775 				struct cfg80211_external_auth_params *params)
27776 {
27777 	int errno;
27778 	struct osif_vdev_sync *vdev_sync;
27779 
27780 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
27781 	if (errno)
27782 		return errno;
27783 
27784 	errno = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
27785 
27786 	osif_vdev_sync_op_stop(vdev_sync);
27787 
27788 	return errno;
27789 }
27790 #endif
27791 
27792 #if defined(WLAN_FEATURE_NAN) && \
27793 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
27794 static int
27795 wlan_hdd_cfg80211_start_nan(struct wiphy *wiphy, struct wireless_dev *wdev,
27796 			    struct cfg80211_nan_conf *conf)
27797 {
27798 	return -EOPNOTSUPP;
27799 }
27800 
27801 static void
27802 wlan_hdd_cfg80211_stop_nan(struct wiphy *wiphy, struct wireless_dev *wdev)
27803 {
27804 }
27805 
27806 static int wlan_hdd_cfg80211_add_nan_func(struct wiphy *wiphy,
27807 					  struct wireless_dev *wdev,
27808 					  struct cfg80211_nan_func *nan_func)
27809 {
27810 	return -EOPNOTSUPP;
27811 }
27812 
27813 static void wlan_hdd_cfg80211_del_nan_func(struct wiphy *wiphy,
27814 					   struct wireless_dev *wdev,
27815 					   u64 cookie)
27816 {
27817 }
27818 
27819 static int wlan_hdd_cfg80211_nan_change_conf(struct wiphy *wiphy,
27820 					     struct wireless_dev *wdev,
27821 					     struct cfg80211_nan_conf *conf,
27822 					     u32 changes)
27823 {
27824 	return -EOPNOTSUPP;
27825 }
27826 #endif
27827 
27828 /**
27829  * wlan_hdd_get_ch_width_from_chan_info - get ch_width as per num channel
27830  * present in scan event
27831  * @info: struct scan_chan_info
27832  *
27833  * Return: phy_ch_width.
27834  */
27835 static enum phy_ch_width
27836 wlan_hdd_get_ch_width_from_chan_info(struct scan_chan_info *info)
27837 {
27838 	enum phy_ch_width scanned_ch_width;
27839 
27840 	switch (info->subband_info.num_chan) {
27841 	case 1:
27842 		scanned_ch_width = CH_WIDTH_20MHZ;
27843 		break;
27844 	case 2:
27845 		scanned_ch_width = CH_WIDTH_40MHZ;
27846 		break;
27847 	case 4:
27848 		scanned_ch_width = CH_WIDTH_80MHZ;
27849 		break;
27850 	case 8:
27851 		scanned_ch_width = CH_WIDTH_160MHZ;
27852 		break;
27853 	default:
27854 		scanned_ch_width = CH_WIDTH_INVALID;
27855 		break;
27856 	}
27857 
27858 	return scanned_ch_width;
27859 }
27860 
27861 /**
27862  * wlan_hdd_fill_subband_scan_info - Fill subband channel info
27863  * @hdd_ctx: hdd context
27864  * @info: struct scan_chan_info
27865  * @chan: scan channel info
27866  *
27867  * update channel info into HDD context on scan done
27868  *
27869  * Return: None.
27870  */
27871 static void wlan_hdd_fill_subband_scan_info(struct hdd_context *hdd_ctx,
27872 					    struct scan_chan_info *info,
27873 					    struct scan_chan_info *chan)
27874 {
27875 	uint8_t idx, info_index, freq_info_num;
27876 	enum phy_ch_width scanned_ch_width;
27877 	const struct bonded_channel_freq *range = NULL;
27878 	qdf_freq_t start_freq, end_freq, sec_2g_freq;
27879 	uint8_t vdev_id = info->subband_info.vdev_id;
27880 	struct assoc_channel_info assoc_chan_info;
27881 
27882 	scanned_ch_width = wlan_hdd_get_ch_width_from_chan_info(info);
27883 	if (scanned_ch_width == CH_WIDTH_INVALID) {
27884 		hdd_debug("vdev %d: Invalid scanned_ch_width", vdev_id);
27885 		return;
27886 	}
27887 
27888 	if (scanned_ch_width == CH_WIDTH_20MHZ) {
27889 		start_freq = info->freq;
27890 		end_freq = info->freq;
27891 	} else if (wlan_reg_is_24ghz_ch_freq(info->freq) &&
27892 		   scanned_ch_width == CH_WIDTH_40MHZ) {
27893 		ucfg_cm_get_associated_ch_info(hdd_ctx->psoc, vdev_id,
27894 					       scanned_ch_width,
27895 					       &assoc_chan_info);
27896 		sec_2g_freq = assoc_chan_info.sec_2g_freq;
27897 		if (!sec_2g_freq) {
27898 			mlme_debug("vdev %d : Invalid sec 2g freq for freq:%d",
27899 				   info->subband_info.vdev_id, info->freq);
27900 			return;
27901 		}
27902 
27903 		hdd_debug("vdev %d :assoc freq %d sec_2g_freq:%d, bw %d",
27904 			  info->subband_info.vdev_id, info->freq,
27905 			  sec_2g_freq, scanned_ch_width);
27906 		if (info->freq > sec_2g_freq) {
27907 			start_freq = sec_2g_freq;
27908 			end_freq = info->freq;
27909 		} else {
27910 			start_freq = info->freq;
27911 			end_freq = sec_2g_freq;
27912 		}
27913 	} else {
27914 		range = wlan_reg_get_bonded_chan_entry(info->freq,
27915 						       scanned_ch_width, 0);
27916 		if (!range) {
27917 			hdd_err("vdev %d: bonded_chan_array is NULL for freq %d, ch_width %d",
27918 				vdev_id, info->freq, scanned_ch_width);
27919 			return;
27920 		}
27921 		start_freq = range->start_freq;
27922 		end_freq = range->end_freq;
27923 	}
27924 
27925 	freq_info_num = info->subband_info.num_chan;
27926 	info_index = 0;
27927 
27928 	hdd_debug("vdev %d: freq :%d bw %d, range [%d-%d], num_freq:%d",
27929 		  vdev_id, info->freq, scanned_ch_width, start_freq,
27930 		  end_freq, freq_info_num);
27931 
27932 	for (idx = 0; idx < NUM_CHANNELS; idx++) {
27933 		if (chan[idx].freq == 0)
27934 			continue;
27935 
27936 		if (start_freq > end_freq || info_index >= freq_info_num ||
27937 		    info_index >= MAX_WIDE_BAND_SCAN_CHAN)
27938 			break;
27939 
27940 		if (chan[idx].freq == start_freq) {
27941 			/*update channel info as per cca busy info */
27942 			info->freq = start_freq;
27943 			info->rx_clear_count =
27944 			   info->subband_info.cca_busy_subband_info[info_index];
27945 
27946 			hdd_update_chan_info(hdd_ctx, &chan[idx], info,
27947 					     info->cmd_flag);
27948 
27949 			hdd_debug("updated info for freq:%u rcc:%d at index:%d",
27950 				  chan[idx].freq, chan[idx].rx_clear_count,
27951 				  idx);
27952 			start_freq += BW_20_MHZ;
27953 			info_index++;
27954 		}
27955 	}
27956 }
27957 
27958 /**
27959  * wlan_hdd_chan_info_cb() - channel info callback
27960  * @info: struct scan_chan_info
27961  *
27962  * Store channel info into HDD context
27963  *
27964  * Return: None.
27965  */
27966 static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
27967 {
27968 	struct hdd_context *hdd_ctx;
27969 	struct scan_chan_info *chan;
27970 	uint8_t idx;
27971 
27972 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
27973 	if (wlan_hdd_validate_context(hdd_ctx) != 0)
27974 		return;
27975 
27976 	if (!hdd_ctx->chan_info) {
27977 		hdd_err("chan_info is NULL");
27978 		return;
27979 	}
27980 
27981 	chan = hdd_ctx->chan_info;
27982 
27983 	if (info->subband_info.is_wide_band_scan) {
27984 		wlan_hdd_fill_subband_scan_info(hdd_ctx, info, chan);
27985 		return;
27986 	}
27987 
27988 	for (idx = 0; idx < NUM_CHANNELS; idx++) {
27989 		if (chan[idx].freq == info->freq) {
27990 			hdd_update_chan_info(hdd_ctx, &chan[idx], info,
27991 				info->cmd_flag);
27992 			hdd_debug("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
27993 				  chan[idx].cmd_flag, chan[idx].freq,
27994 				  chan[idx].noise_floor,
27995 				  chan[idx].cycle_count,
27996 				  chan[idx].rx_clear_count,
27997 				  chan[idx].clock_freq, chan[idx].cmd_flag,
27998 				  chan[idx].tx_frame_count, idx);
27999 			if (chan[idx].freq == 0)
28000 				break;
28001 
28002 		}
28003 	}
28004 }
28005 
28006 /**
28007  * wlan_hdd_init_chan_info() - init chan info in hdd context
28008  * @hdd_ctx: HDD context pointer
28009  *
28010  * Return: none
28011  */
28012 void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
28013 {
28014 	uint32_t num_2g, num_5g, index = 0;
28015 	mac_handle_t mac_handle;
28016 
28017 	hdd_ctx->chan_info = NULL;
28018 	if (!ucfg_scan_is_snr_monitor_enabled(hdd_ctx->psoc)) {
28019 		hdd_debug("SNR monitoring is disabled");
28020 		return;
28021 	}
28022 
28023 	hdd_ctx->chan_info =
28024 		qdf_mem_malloc(sizeof(struct scan_chan_info)
28025 					* NUM_CHANNELS);
28026 	if (!hdd_ctx->chan_info)
28027 		return;
28028 	mutex_init(&hdd_ctx->chan_info_lock);
28029 
28030 	num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
28031 	for (; index < num_2g; index++) {
28032 		hdd_ctx->chan_info[index].freq =
28033 			hdd_channels_2_4_ghz[index].center_freq;
28034 	}
28035 
28036 	num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
28037 	for (; (index - num_2g) < num_5g; index++)
28038 		hdd_ctx->chan_info[index].freq =
28039 			hdd_channels_5_ghz[index - num_2g].center_freq;
28040 
28041 	index = num_2g + num_5g;
28042 	index += wlan_hdd_populate_5dot9_chan_info(hdd_ctx, index);
28043 	index += wlan_hdd_populate_6g_chan_info(hdd_ctx, index);
28044 	hdd_debug("Number of channels populated : %d", index);
28045 
28046 	mac_handle = hdd_ctx->mac_handle;
28047 	sme_set_chan_info_callback(mac_handle, &wlan_hdd_chan_info_cb);
28048 }
28049 
28050 /**
28051  * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
28052  * @hdd_ctx: hdd context pointer
28053  *
28054  * Return: none
28055  */
28056 void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
28057 {
28058 	struct scan_chan_info *chan;
28059 
28060 	chan = hdd_ctx->chan_info;
28061 	hdd_ctx->chan_info = NULL;
28062 	if (chan)
28063 		qdf_mem_free(chan);
28064 }
28065 
28066 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) || defined(CFG80211_11BE_BASIC)
28067 #define SET_RATE_INFO_BW_320 RATE_INFO_BW_320
28068 #else
28069 #define SET_RATE_INFO_BW_320 RATE_INFO_BW_160
28070 #endif
28071 
28072 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
28073 static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
28074 {
28075 	switch (hdd_bw) {
28076 	case HDD_RATE_BW_5:
28077 		return RATE_INFO_BW_5;
28078 	case HDD_RATE_BW_10:
28079 		return RATE_INFO_BW_10;
28080 	case HDD_RATE_BW_20:
28081 		return RATE_INFO_BW_20;
28082 	case HDD_RATE_BW_40:
28083 		return RATE_INFO_BW_40;
28084 	case HDD_RATE_BW_80:
28085 		return RATE_INFO_BW_80;
28086 	case HDD_RATE_BW_160:
28087 		return RATE_INFO_BW_160;
28088 	case HDD_RATE_BW_320:
28089 		return SET_RATE_INFO_BW_320;
28090 	}
28091 
28092 	hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
28093 
28094 	return RATE_INFO_BW_20;
28095 }
28096 
28097 void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
28098 {
28099 	info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
28100 }
28101 #else
28102 static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
28103 {
28104 	switch (hdd_bw) {
28105 	case HDD_RATE_BW_5:
28106 	case HDD_RATE_BW_10:
28107 	case HDD_RATE_BW_20:
28108 		return (enum rate_info_flags)0;
28109 	case HDD_RATE_BW_40:
28110 		return RATE_INFO_FLAGS_40_MHZ_WIDTH;
28111 	case HDD_RATE_BW_80:
28112 		return RATE_INFO_FLAGS_80_MHZ_WIDTH;
28113 	case HDD_RATE_BW_160:
28114 		return RATE_INFO_FLAGS_160_MHZ_WIDTH;
28115 	}
28116 
28117 	hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
28118 
28119 	return (enum rate_info_flags)0;
28120 }
28121 
28122 void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
28123 {
28124 	const enum rate_info_flags all_bws =
28125 		RATE_INFO_FLAGS_40_MHZ_WIDTH |
28126 		RATE_INFO_FLAGS_80_MHZ_WIDTH |
28127 		RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
28128 		RATE_INFO_FLAGS_160_MHZ_WIDTH;
28129 
28130 	info->flags &= ~all_bws;
28131 	info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
28132 }
28133 #endif
28134 
28135 #if defined(CFG80211_EXTERNAL_DH_UPDATE_SUPPORT) || \
28136 (LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0))
28137 
28138 #ifdef WLAN_MLD_AP_OWE_INFO_SUPPORT
28139 static void
28140 hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter *adapter,
28141 			    struct cfg80211_update_owe_info *owe_info,
28142 			    uint8_t *peer_mac)
28143 {
28144 	bool is_mlo_vdev;
28145 	struct wlan_objmgr_peer *peer;
28146 	struct wlan_objmgr_vdev *vdev;
28147 	uint8_t *peer_mld_addr;
28148 
28149 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
28150 	if (!vdev)
28151 		return;
28152 
28153 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
28154 	if (is_mlo_vdev)
28155 		owe_info->link_id = wlan_vdev_get_link_id(vdev);
28156 	else
28157 		owe_info->link_id = -1;
28158 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
28159 
28160 	if (!is_mlo_vdev)
28161 		return;
28162 
28163 	peer = wlan_objmgr_get_peer_by_mac(adapter->hdd_ctx->psoc,
28164 					   peer_mac, WLAN_OSIF_ID);
28165 	if (!peer) {
28166 		hdd_err("Peer not found with MAC " QDF_MAC_ADDR_FMT,
28167 			QDF_MAC_ADDR_REF(peer_mac));
28168 		return;
28169 	}
28170 
28171 	peer_mld_addr = wlan_peer_mlme_get_mldaddr(peer);
28172 	qdf_mem_copy(&owe_info->peer_mld_addr[0], peer_mld_addr, ETH_ALEN);
28173 	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
28174 }
28175 #elif defined(CFG80211_MLD_AP_STA_CONNECT_UPSTREAM_SUPPORT)
28176 static void
28177 hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter *adapter,
28178 			    struct cfg80211_update_owe_info *owe_info,
28179 			    uint8_t *peer_mac)
28180 {
28181 	bool is_mlo_vdev;
28182 	struct wlan_objmgr_peer *peer;
28183 	struct wlan_objmgr_vdev *vdev;
28184 	uint8_t *peer_mld_addr;
28185 
28186 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink,
28187 					   WLAN_HDD_ID_OBJ_MGR);
28188 	if (!vdev)
28189 		return;
28190 
28191 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(vdev);
28192 	if (!is_mlo_vdev) {
28193 		owe_info->assoc_link_id = -1;
28194 		hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
28195 		return;
28196 	}
28197 
28198 	owe_info->assoc_link_id = wlan_vdev_get_link_id(vdev);
28199 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
28200 
28201 	peer = wlan_objmgr_get_peer_by_mac(adapter->hdd_ctx->psoc,
28202 					   peer_mac, WLAN_HDD_ID_OBJ_MGR);
28203 	if (!peer) {
28204 		hdd_err("Peer not found with MAC " QDF_MAC_ADDR_FMT,
28205 			QDF_MAC_ADDR_REF(peer_mac));
28206 		return;
28207 	}
28208 
28209 	peer_mld_addr = wlan_peer_mlme_get_mldaddr(peer);
28210 	qdf_mem_copy(&owe_info->peer_mld_addr[0], peer_mld_addr, ETH_ALEN);
28211 	wlan_objmgr_peer_release_ref(peer, WLAN_HDD_ID_OBJ_MGR);
28212 }
28213 #else
28214 static void
28215 hdd_ml_sap_owe_fill_ml_info(struct hdd_adapter *adapter,
28216 			    struct cfg80211_update_owe_info *owe_info,
28217 			    uint8_t *peer_mac)
28218 {
28219 }
28220 #endif
28221 
28222 void hdd_send_update_owe_info_event(struct hdd_adapter *adapter,
28223 				    uint8_t sta_addr[],
28224 				    uint8_t *owe_ie,
28225 				    uint32_t owe_ie_len)
28226 {
28227 	struct cfg80211_update_owe_info owe_info;
28228 	struct net_device *dev = adapter->dev;
28229 
28230 	hdd_enter_dev(dev);
28231 
28232 	qdf_mem_zero(&owe_info, sizeof(owe_info));
28233 	qdf_mem_copy(owe_info.peer, sta_addr, ETH_ALEN);
28234 	hdd_ml_sap_owe_fill_ml_info(adapter, &owe_info, sta_addr);
28235 	owe_info.ie = owe_ie;
28236 	owe_info.ie_len = owe_ie_len;
28237 
28238 	cfg80211_update_owe_info_event(dev, &owe_info, GFP_KERNEL);
28239 
28240 	hdd_exit();
28241 }
28242 #endif
28243 
28244 #define MAX_PDEV_TXRX_PARAMS 2
28245 /* params being sent:
28246  * 1.wmi_pdev_param_tx_chain_mask
28247  * 2.wmi_pdev_param_rx_chain_mask
28248  */
28249 static int __wlan_hdd_cfg80211_set_chainmask(struct wiphy *wiphy,
28250 					     uint32_t tx_mask,
28251 					     uint32_t rx_mask)
28252 {
28253 	int ret;
28254 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
28255 	enum hdd_chain_mode chains;
28256 	struct dev_set_param setparam[MAX_PDEV_TXRX_PARAMS] = {};
28257 	uint8_t index = 0;
28258 	uint8_t ll_lt_sap_vdev_id;
28259 
28260 	ret = wlan_hdd_validate_context(hdd_ctx);
28261 	if (ret)
28262 		return -EINVAL;
28263 
28264 	if (hdd_ctx->num_rf_chains != HDD_ANTENNA_MODE_2X2 ||
28265 	    !ucfg_mlme_is_chain_mask_supported(hdd_ctx->psoc)) {
28266 		hdd_info_rl("Chainmask can't be configured, num of rf chain %d",
28267 			    hdd_ctx->num_rf_chains);
28268 		return -ENOTSUPP;
28269 	}
28270 	chains = HDD_CHAIN_MODE_2X2;
28271 	if (!tx_mask || tx_mask > chains || !rx_mask || rx_mask > chains) {
28272 		hdd_err_rl("Invalid masks. txMask: %d rxMask: %d num_rf_chains: %d",
28273 			   tx_mask, rx_mask, hdd_ctx->num_rf_chains);
28274 
28275 		return -EINVAL;
28276 	}
28277 
28278 	ll_lt_sap_vdev_id =
28279 			wlan_policy_mgr_get_ll_lt_sap_vdev_id(hdd_ctx->psoc);
28280 	if (ll_lt_sap_vdev_id != WLAN_INVALID_VDEV_ID) {
28281 		hdd_info_rl("LL_LT_SAP vdev %d present, chainmask config not allowed",
28282 			    ll_lt_sap_vdev_id);
28283 		return -ENOTSUPP;
28284 	}
28285 
28286 	if (sme_validate_txrx_chain_mask(wmi_pdev_param_tx_chain_mask, tx_mask))
28287 		return -EINVAL;
28288 
28289 	ret = mlme_check_index_setparam(
28290 				setparam, wmi_pdev_param_tx_chain_mask,
28291 				tx_mask, index++, MAX_PDEV_TXRX_PARAMS);
28292 	if (QDF_IS_STATUS_ERROR(ret)) {
28293 		hdd_err("failed at wmi_pdev_param_tx_chain_mask");
28294 		return -EINVAL;
28295 	}
28296 
28297 	if (sme_validate_txrx_chain_mask(wmi_pdev_param_rx_chain_mask, rx_mask))
28298 		return -EINVAL;
28299 
28300 	ret = mlme_check_index_setparam(
28301 				setparam, wmi_pdev_param_rx_chain_mask,
28302 				rx_mask, index++, MAX_PDEV_TXRX_PARAMS);
28303 	if (QDF_IS_STATUS_ERROR(ret)) {
28304 		hdd_err("failed at wmi_pdev_param_rx_chain_mask");
28305 		return -EINVAL;
28306 	}
28307 
28308 	ret = wma_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
28309 						  WMI_PDEV_ID_SOC, setparam,
28310 						  index);
28311 	if (QDF_IS_STATUS_ERROR(ret))
28312 		hdd_err("failed to send TX, RX chain mask params");
28313 
28314 	return ret;
28315 }
28316 
28317 static int wlan_hdd_cfg80211_set_chainmask(struct wiphy *wiphy,
28318 					   uint32_t tx_mask,
28319 					   uint32_t rx_mask)
28320 {
28321 	struct osif_psoc_sync *psoc_sync;
28322 	int errno;
28323 
28324 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
28325 	if (errno)
28326 		return errno;
28327 
28328 	errno = __wlan_hdd_cfg80211_set_chainmask(wiphy, tx_mask, rx_mask);
28329 	osif_psoc_sync_op_stop(psoc_sync);
28330 
28331 	return errno;
28332 }
28333 
28334 static int __wlan_hdd_cfg80211_get_chainmask(struct wiphy *wiphy,
28335 					     uint32_t *tx_mask,
28336 					     uint32_t *rx_mask)
28337 
28338 {
28339 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
28340 	int ret;
28341 
28342 	ret = wlan_hdd_validate_context(hdd_ctx);
28343 	if (ret)
28344 		return -EINVAL;
28345 
28346 	*tx_mask = wma_cli_get_command(0, wmi_pdev_param_tx_chain_mask,
28347 				       PDEV_CMD);
28348 	*rx_mask = wma_cli_get_command(0, wmi_pdev_param_rx_chain_mask,
28349 				       PDEV_CMD);
28350 
28351 	/* if 0 return max value as 0 mean no set cmnd received yet */
28352 	if (!*tx_mask)
28353 		*tx_mask = hdd_ctx->num_rf_chains == HDD_ANTENNA_MODE_2X2 ?
28354 				HDD_CHAIN_MODE_2X2 : HDD_CHAIN_MODE_1X1;
28355 	if (!*rx_mask)
28356 		*rx_mask = hdd_ctx->num_rf_chains == HDD_ANTENNA_MODE_2X2 ?
28357 				HDD_CHAIN_MODE_2X2 : HDD_CHAIN_MODE_1X1;
28358 	hdd_debug("tx_mask: %d rx_mask: %d", *tx_mask, *rx_mask);
28359 
28360 	return 0;
28361 }
28362 
28363 static int wlan_hdd_cfg80211_get_chainmask(struct wiphy *wiphy,
28364 					   uint32_t *tx_mask,
28365 					   uint32_t *rx_mask)
28366 {
28367 	struct osif_psoc_sync *psoc_sync;
28368 	int errno;
28369 
28370 	errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
28371 	if (errno)
28372 		return errno;
28373 
28374 	errno = __wlan_hdd_cfg80211_get_chainmask(wiphy, tx_mask, rx_mask);
28375 	osif_psoc_sync_op_stop(psoc_sync);
28376 
28377 	return errno;
28378 }
28379 
28380 enum qca_wlan_802_11_mode
28381 hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode)
28382 {
28383 	switch (mode) {
28384 	case eCSR_CFG_DOT11_MODE_11A:
28385 		return QCA_WLAN_802_11_MODE_11A;
28386 	case eCSR_CFG_DOT11_MODE_11B:
28387 		return QCA_WLAN_802_11_MODE_11B;
28388 	case eCSR_CFG_DOT11_MODE_11G:
28389 		return QCA_WLAN_802_11_MODE_11G;
28390 	case eCSR_CFG_DOT11_MODE_11N:
28391 		return QCA_WLAN_802_11_MODE_11N;
28392 	case eCSR_CFG_DOT11_MODE_11AC:
28393 		return QCA_WLAN_802_11_MODE_11AC;
28394 	case eCSR_CFG_DOT11_MODE_11G_ONLY:
28395 		return QCA_WLAN_802_11_MODE_11G;
28396 	case eCSR_CFG_DOT11_MODE_11N_ONLY:
28397 		return QCA_WLAN_802_11_MODE_11N;
28398 	case eCSR_CFG_DOT11_MODE_11AC_ONLY:
28399 		return QCA_WLAN_802_11_MODE_11AC;
28400 	case eCSR_CFG_DOT11_MODE_11AX:
28401 		return QCA_WLAN_802_11_MODE_11AX;
28402 	case eCSR_CFG_DOT11_MODE_11AX_ONLY:
28403 		return QCA_WLAN_802_11_MODE_11AX;
28404 	case eCSR_CFG_DOT11_MODE_11BE:
28405 	case eCSR_CFG_DOT11_MODE_11BE_ONLY:
28406 		return QCA_WLAN_802_11_MODE_11BE;
28407 	case eCSR_CFG_DOT11_MODE_ABG:
28408 	case eCSR_CFG_DOT11_MODE_AUTO:
28409 	default:
28410 		return QCA_WLAN_802_11_MODE_INVALID;
28411 	}
28412 }
28413 
28414 enum qca_wlan_802_11_mode
28415 hdd_convert_phymode_to_80211mode(eCsrPhyMode mode)
28416 {
28417 	switch (mode) {
28418 	case eCSR_DOT11_MODE_11a:
28419 		return QCA_WLAN_802_11_MODE_11A;
28420 	case eCSR_DOT11_MODE_11b:
28421 		return QCA_WLAN_802_11_MODE_11B;
28422 	case eCSR_DOT11_MODE_11g:
28423 	case eCSR_DOT11_MODE_11g_ONLY:
28424 		return QCA_WLAN_802_11_MODE_11G;
28425 	case eCSR_DOT11_MODE_11n:
28426 	case eCSR_DOT11_MODE_11n_ONLY:
28427 		return QCA_WLAN_802_11_MODE_11N;
28428 	case eCSR_DOT11_MODE_11ac:
28429 	case eCSR_DOT11_MODE_11ac_ONLY:
28430 		return QCA_WLAN_802_11_MODE_11AC;
28431 	case eCSR_DOT11_MODE_11ax:
28432 	case eCSR_DOT11_MODE_11ax_ONLY:
28433 		return QCA_WLAN_802_11_MODE_11AX;
28434 	case eCSR_DOT11_MODE_11be:
28435 	case eCSR_DOT11_MODE_11be_ONLY:
28436 		return QCA_WLAN_802_11_MODE_11BE;
28437 	case eCSR_DOT11_MODE_abg:
28438 	case eCSR_DOT11_MODE_AUTO:
28439 	default:
28440 		return QCA_WLAN_802_11_MODE_INVALID;
28441 	}
28442 }
28443 
28444 bool hdd_is_legacy_connection(struct wlan_hdd_link_info *link_info)
28445 {
28446 	struct hdd_station_ctx *sta_ctx;
28447 	int connection_mode = QCA_WLAN_802_11_MODE_INVALID;
28448 	enum csr_cfgdot11mode cfgmode;
28449 	uint16_t tdls_connected_peer;
28450 
28451 	tdls_connected_peer = hdd_get_tdls_connected_peer_count(link_info);
28452 	if (tdls_connected_peer)
28453 		return false;
28454 
28455 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
28456 	cfgmode = sta_ctx->conn_info.dot11mode;
28457 	connection_mode = hdd_convert_cfgdot11mode_to_80211mode(cfgmode);
28458 	if (connection_mode == QCA_WLAN_802_11_MODE_11A ||
28459 	    connection_mode == QCA_WLAN_802_11_MODE_11B ||
28460 	    connection_mode == QCA_WLAN_802_11_MODE_11G)
28461 		return true;
28462 	else
28463 		return false;
28464 }
28465 
28466 static int __wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
28467 					   struct wireless_dev *wdev,
28468 					   struct cfg80211_chan_def *chandef,
28469 					   int link_id)
28470 {
28471 	struct net_device *dev = wdev->netdev;
28472 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
28473 	struct hdd_context *hdd_ctx;
28474 	bool is_legacy_phymode = false;
28475 	struct wlan_objmgr_vdev *vdev;
28476 	uint32_t chan_freq;
28477 	struct wlan_hdd_link_info *link_info;
28478 	uint8_t vdev_id;
28479 	enum phy_ch_width ch_width;
28480 	enum wlan_phymode peer_phymode;
28481 	struct hdd_station_ctx *sta_ctx = NULL;
28482 	struct ch_params ch_params = {0};
28483 
28484 	hdd_enter_dev(wdev->netdev);
28485 
28486 	if (hdd_validate_adapter(adapter))
28487 		return -EINVAL;
28488 
28489 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
28490 	if (wlan_hdd_validate_context(hdd_ctx))
28491 		return -EINVAL;
28492 
28493 	if ((adapter->device_mode == QDF_STA_MODE) ||
28494 	    (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
28495 
28496 		if (!hdd_cm_is_vdev_associated(adapter->deflink))
28497 			return -EINVAL;
28498 
28499 		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter->deflink);
28500 		if (sta_ctx->conn_info.dot11mode < eCSR_CFG_DOT11_MODE_11N)
28501 			is_legacy_phymode = true;
28502 
28503 	} else if ((adapter->device_mode == QDF_SAP_MODE) ||
28504 			(adapter->device_mode == QDF_P2P_GO_MODE)) {
28505 		struct hdd_ap_ctx *ap_ctx;
28506 
28507 		ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter->deflink);
28508 
28509 		if (!test_bit(SOFTAP_BSS_STARTED,
28510 			      &adapter->deflink->link_flags))
28511 			return -EINVAL;
28512 
28513 		switch (ap_ctx->sap_config.SapHw_mode) {
28514 		case eCSR_DOT11_MODE_11n:
28515 		case eCSR_DOT11_MODE_11n_ONLY:
28516 		case eCSR_DOT11_MODE_11ac:
28517 		case eCSR_DOT11_MODE_11ac_ONLY:
28518 		case eCSR_DOT11_MODE_11ax:
28519 		case eCSR_DOT11_MODE_11ax_ONLY:
28520 			is_legacy_phymode = false;
28521 			break;
28522 		default:
28523 			is_legacy_phymode = true;
28524 			break;
28525 		}
28526 	} else {
28527 		return -EINVAL;
28528 	}
28529 
28530 	vdev = wlan_key_get_link_vdev(adapter, WLAN_OSIF_ID, link_id);
28531 	if (!vdev)
28532 		return -EINVAL;
28533 
28534 	if (adapter->device_mode == QDF_STA_MODE) {
28535 		vdev_id = wlan_vdev_get_id(vdev);
28536 		link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
28537 		if (!link_info || !hdd_cm_is_vdev_associated(link_info)) {
28538 			wlan_key_put_link_vdev(vdev, WLAN_OSIF_ID);
28539 			return -EBUSY;
28540 		}
28541 		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
28542 	}
28543 
28544 	chan_freq = vdev->vdev_mlme.des_chan->ch_freq;
28545 	chandef->center_freq1 = vdev->vdev_mlme.des_chan->ch_cfreq1;
28546 	chandef->center_freq2 = 0;
28547 	chandef->chan = ieee80211_get_channel(wiphy, chan_freq);
28548 
28549 	ch_width = vdev->vdev_mlme.des_chan->ch_width;
28550 	if (adapter->device_mode == QDF_STA_MODE ||
28551 	    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
28552 		/* For STA/P2P CLI get the peer pymode as, in some IOT
28553 		 * cases VDEV BW will not be same as peer BW
28554 		 */
28555 		mlme_get_peer_phymode(hdd_ctx->psoc,
28556 				      sta_ctx->conn_info.bssid.bytes,
28557 				      &peer_phymode);
28558 		ch_width = wlan_mlme_get_ch_width_from_phymode(peer_phymode);
28559 	}
28560 
28561 	ch_params.ch_width = ch_width;
28562 	wlan_reg_set_channel_params_for_pwrmode(hdd_ctx->pdev,
28563 						chan_freq, 0, &ch_params,
28564 						REG_CURRENT_PWR_MODE);
28565 	chandef->center_freq1 = ch_params.mhz_freq_seg0;
28566 
28567 	switch (ch_width) {
28568 	case CH_WIDTH_20MHZ:
28569 		if (is_legacy_phymode)
28570 			chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
28571 		else
28572 			chandef->width = NL80211_CHAN_WIDTH_20;
28573 		break;
28574 	case CH_WIDTH_40MHZ:
28575 		chandef->width = NL80211_CHAN_WIDTH_40;
28576 		break;
28577 	case CH_WIDTH_80MHZ:
28578 		chandef->width = NL80211_CHAN_WIDTH_80;
28579 		break;
28580 	case CH_WIDTH_160MHZ:
28581 		chandef->width = NL80211_CHAN_WIDTH_160;
28582 		/* Set center_freq1 to center frequency of complete 160MHz */
28583 		chandef->center_freq1 = vdev->vdev_mlme.des_chan->ch_cfreq2;
28584 		break;
28585 	case CH_WIDTH_80P80MHZ:
28586 		chandef->width = NL80211_CHAN_WIDTH_80P80;
28587 		chandef->center_freq2 = vdev->vdev_mlme.des_chan->ch_cfreq2;
28588 		break;
28589 	case CH_WIDTH_5MHZ:
28590 		chandef->width = NL80211_CHAN_WIDTH_5;
28591 		break;
28592 	case CH_WIDTH_10MHZ:
28593 		chandef->width = NL80211_CHAN_WIDTH_10;
28594 		break;
28595 	default:
28596 		chandef->width = NL80211_CHAN_WIDTH_20;
28597 		break;
28598 	}
28599 
28600 	wlan_hdd_set_chandef(vdev, chandef);
28601 
28602 	wlan_key_put_link_vdev(vdev, WLAN_OSIF_ID);
28603 
28604 	hdd_debug("primary_freq:%d, ch_width:%d, center_freq1:%d, center_freq2:%d",
28605 		  chan_freq, chandef->width, chandef->center_freq1,
28606 		  chandef->center_freq2);
28607 	return 0;
28608 }
28609 
28610 /**
28611  * wlan_hdd_cfg80211_get_channel() - API to process cfg80211 get_channel request
28612  * @wiphy: Pointer to wiphy
28613  * @wdev: Pointer to wireless device
28614  * @link_id: Channel link ID
28615  * @chandef: Pointer to channel definition
28616  *
28617  * Return: 0 for success, non zero for failure
28618  */
28619 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
28620 static int wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
28621 					 struct wireless_dev *wdev,
28622 					 unsigned int link_id,
28623 					 struct cfg80211_chan_def *chandef)
28624 {
28625 	int errno;
28626 	struct osif_vdev_sync *vdev_sync;
28627 
28628 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
28629 	if (errno)
28630 		return errno;
28631 
28632 	errno = __wlan_hdd_cfg80211_get_channel(wiphy, wdev, chandef, link_id);
28633 
28634 	osif_vdev_sync_op_stop(vdev_sync);
28635 
28636 	return errno;
28637 }
28638 #else
28639 static int wlan_hdd_cfg80211_get_channel(struct wiphy *wiphy,
28640 					 struct wireless_dev *wdev,
28641 					 struct cfg80211_chan_def *chandef)
28642 {
28643 	int errno;
28644 	struct osif_vdev_sync *vdev_sync;
28645 	/* Legacy purposes */
28646 	int link_id = -1;
28647 
28648 	errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
28649 	if (errno)
28650 		return errno;
28651 
28652 	errno = __wlan_hdd_cfg80211_get_channel(wiphy, wdev, chandef, link_id);
28653 
28654 	osif_vdev_sync_op_stop(vdev_sync);
28655 
28656 	return errno;
28657 }
28658 #endif
28659 
28660 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
28661 static int
28662 hdd_check_he_bitmask_for_single_rate(enum nl80211_band band,
28663 				     const struct cfg80211_bitrate_mask *mask)
28664 {
28665 	int he_rates = 0, i;
28666 
28667 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].he_mcs); i++)
28668 		he_rates += qdf_get_hweight16(mask->control[band].he_mcs[i]);
28669 
28670 	return he_rates;
28671 }
28672 
28673 static void
28674 hdd_get_he_bitrate_params_for_band(enum nl80211_band band,
28675 				   const struct cfg80211_bitrate_mask *mask,
28676 				   uint8_t *nss, uint8_t *rate_index,
28677 				   int *bit_rate)
28678 {
28679 	int i;
28680 
28681 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].he_mcs); i++) {
28682 		if (qdf_get_hweight16(mask->control[band].he_mcs[i]) == 1) {
28683 			*nss = i;
28684 			*rate_index = (ffs(mask->control[band].he_mcs[i]) - 1);
28685 			*bit_rate = hdd_assemble_rate_code(WMI_RATE_PREAMBLE_HE,
28686 							   *nss, *rate_index);
28687 			break;
28688 		}
28689 	}
28690 }
28691 #else
28692 static inline int
28693 hdd_check_he_bitmask_for_single_rate(enum nl80211_band band,
28694 				     const struct cfg80211_bitrate_mask *mask)
28695 {
28696 	return 0;
28697 }
28698 
28699 static inline void
28700 hdd_get_he_bitrate_params_for_band(enum nl80211_band band,
28701 				   const struct cfg80211_bitrate_mask *mask,
28702 				   uint8_t *nss, uint8_t *rate_index,
28703 				   int *bit_rate)
28704 
28705 {
28706 }
28707 #endif
28708 
28709 static bool hdd_check_bitmask_for_single_rate(enum nl80211_band band,
28710 				const struct cfg80211_bitrate_mask *mask)
28711 {
28712 	int num_rates = 0, i;
28713 
28714 	num_rates += qdf_get_hweight32(mask->control[band].legacy);
28715 
28716 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].ht_mcs); i++)
28717 		num_rates += qdf_get_hweight8(mask->control[band].ht_mcs[i]);
28718 
28719 	for (i = 0; i < QDF_ARRAY_SIZE(mask->control[band].vht_mcs); i++)
28720 		num_rates += qdf_get_hweight16(mask->control[band].vht_mcs[i]);
28721 
28722 	num_rates += hdd_check_he_bitmask_for_single_rate(band, mask);
28723 
28724 	return num_rates ? true : false;
28725 }
28726 
28727 static int __wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
28728 						struct net_device *dev,
28729 						const u8 *peer,
28730 				       const struct cfg80211_bitrate_mask *mask)
28731 {
28732 	enum nl80211_band band;
28733 	int errno;
28734 	struct hdd_adapter *adapter = netdev_priv(dev);
28735 	uint8_t nss, i;
28736 	int bit_rate = -1;
28737 	uint8_t rate_index;
28738 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
28739 	uint8_t vdev_id;
28740 	u8 gi_val = 0;
28741 #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
28742 	uint8_t auto_rate_he_gi = 0;
28743 #endif
28744 
28745 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() ||
28746 	    QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) {
28747 		hdd_err("Command not allowed in mode");
28748 		return -EINVAL;
28749 	}
28750 
28751 	errno = hdd_validate_adapter(adapter);
28752 	if (errno)
28753 		return errno;
28754 
28755 	errno = wlan_hdd_validate_context(hdd_ctx);
28756 	if (errno)
28757 		return errno;
28758 
28759 	vdev_id = adapter->deflink->vdev_id;
28760 
28761 	for (band = NL80211_BAND_2GHZ; band <= NL80211_BAND_5GHZ; band++) {
28762 		/* Support configuring only one bitrate */
28763 		if (!hdd_check_bitmask_for_single_rate(band, mask)) {
28764 			hdd_err("Multiple bitrate set not supported for band %u",
28765 				band);
28766 			errno = -EINVAL;
28767 			continue;
28768 		}
28769 
28770 		if (!qdf_get_hweight32(mask->control[band].legacy)) {
28771 			hdd_err("Legacy bit rate setting not supported for band %u",
28772 				band);
28773 			errno = -EINVAL;
28774 			continue;
28775 		}
28776 
28777 		for (i = 0;
28778 			i < QDF_ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
28779 			if (qdf_get_hweight8(mask->control[band].ht_mcs[i])
28780 									== 1) {
28781 				nss = i;
28782 				rate_index =
28783 				      (ffs(mask->control[band].ht_mcs[i]) - 1);
28784 				bit_rate = hdd_assemble_rate_code(
28785 						WMI_RATE_PREAMBLE_HT,
28786 						nss, rate_index);
28787 				goto configure_fw;
28788 			}
28789 		}
28790 
28791 		for (i = 0;
28792 			i < QDF_ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
28793 			if (qdf_get_hweight16(mask->control[band].vht_mcs[i])
28794 									== 1) {
28795 				nss = i;
28796 				rate_index =
28797 				     (ffs(mask->control[band].vht_mcs[i]) - 1);
28798 				bit_rate = hdd_assemble_rate_code(
28799 						WMI_RATE_PREAMBLE_VHT,
28800 						nss, rate_index);
28801 				goto configure_fw;
28802 			}
28803 		}
28804 
28805 		if (qdf_get_hweight32(mask->control[band].legacy) == 1) {
28806 			rate_index = (ffs(mask->control[band].legacy) - 1);
28807 			nss = 0;
28808 			if (band == NL80211_BAND_5GHZ)
28809 				rate_index += 4;
28810 			if (rate_index < 4)
28811 				bit_rate = hdd_assemble_rate_code(
28812 					WMI_RATE_PREAMBLE_CCK, nss,
28813 					hdd_legacy_rates[rate_index].hw_value);
28814 			else if (rate_index >= 4 && rate_index < 12)
28815 				bit_rate = hdd_assemble_rate_code(
28816 					WMI_RATE_PREAMBLE_OFDM, nss,
28817 					hdd_legacy_rates[rate_index].hw_value);
28818 		}
28819 
28820 		hdd_get_he_bitrate_params_for_band(band, mask, &nss,
28821 						   &rate_index, &bit_rate);
28822 
28823 configure_fw:
28824 		if (bit_rate != -1) {
28825 			hdd_debug("wmi_vdev_param_fixed_rate val %d", bit_rate);
28826 
28827 			errno = wma_cli_set_command(adapter->deflink->vdev_id,
28828 						    wmi_vdev_param_fixed_rate,
28829 						    bit_rate, VDEV_CMD);
28830 
28831 			if (errno)
28832 				hdd_err("Failed to set firmware, errno %d",
28833 					errno);
28834 		}
28835 
28836 
28837 #if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
28838 		if (NL80211_RATE_INFO_HE_GI_0_8 == mask->control[band].he_gi) {
28839 			auto_rate_he_gi = AUTO_RATE_GI_800NS;
28840 			gi_val = 1;
28841 		} else if (NL80211_RATE_INFO_HE_GI_1_6 ==
28842 			   mask->control[band].he_gi) {
28843 			auto_rate_he_gi = AUTO_RATE_GI_1600NS;
28844 			gi_val = 2;
28845 		} else if (NL80211_RATE_INFO_HE_GI_3_2 ==
28846 			   mask->control[band].he_gi) {
28847 			auto_rate_he_gi = AUTO_RATE_GI_3200NS;
28848 			gi_val = 3;
28849 		}
28850 		if (auto_rate_he_gi) {
28851 			errno = sme_set_auto_rate_he_sgi(
28852 						hdd_ctx->mac_handle,
28853 						adapter->deflink->vdev_id,
28854 						auto_rate_he_gi);
28855 			if (errno)
28856 				hdd_err("auto rate GI %d set fail, status %d",
28857 					auto_rate_he_gi, errno);
28858 
28859 			errno = sme_update_ht_config(
28860 					hdd_ctx->mac_handle,
28861 					adapter->deflink->vdev_id,
28862 					WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ,
28863 					gi_val);
28864 
28865 			if (errno) {
28866 				hdd_err("cfg set failed, value %d status %d",
28867 					gi_val, errno);
28868 			}
28869 		} else
28870 #endif
28871 		if (mask->control[band].gi) {
28872 			if (NL80211_TXRATE_FORCE_SGI == mask->control[band].gi)
28873 				gi_val = 0;
28874 			else
28875 				gi_val = 1;
28876 
28877 			errno = sme_update_ht_config(
28878 					hdd_ctx->mac_handle,
28879 					adapter->deflink->vdev_id,
28880 					WNI_CFG_HT_CAP_INFO_SHORT_GI_20MHZ,
28881 					gi_val);
28882 
28883 			if (errno)
28884 				hdd_err("cfg set failed, value %d status %d",
28885 					mask->control[band].gi, errno);
28886 		}
28887 	}
28888 
28889 	return errno;
28890 }
28891 
28892 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
28893 static int wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
28894 					      struct net_device *netdev,
28895 					      unsigned int link_id,
28896 					      const u8 *peer,
28897 				       const struct cfg80211_bitrate_mask *mask)
28898 #else
28899 static int wlan_hdd_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
28900 					      struct net_device *netdev,
28901 					      const u8 *peer,
28902 				       const struct cfg80211_bitrate_mask *mask)
28903 #endif
28904 {
28905 	int errno;
28906 	struct osif_vdev_sync *vdev_sync;
28907 
28908 	errno = osif_vdev_sync_op_start(netdev, &vdev_sync);
28909 	if (errno) {
28910 		hdd_err("vdev_sync_op_start failure");
28911 		return errno;
28912 	}
28913 
28914 	errno = __wlan_hdd_cfg80211_set_bitrate_mask(wiphy, netdev, peer,
28915 						     mask);
28916 
28917 	osif_vdev_sync_op_stop(vdev_sync);
28918 
28919 	return errno;
28920 }
28921 
28922 static int __wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
28923 					       struct net_device *dev,
28924 					       const u8 *buf, size_t len,
28925 					       const u8 *src, const u8 *dest,
28926 						__be16 proto, bool unencrypted)
28927 {
28928 	qdf_nbuf_t nbuf;
28929 	struct ethhdr *ehdr;
28930 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
28931 
28932 	hdd_enter();
28933 
28934 	nbuf = dev_alloc_skb(len + sizeof(struct ethhdr));
28935 	if (!nbuf)
28936 		return -ENOMEM;
28937 
28938 	skb_reserve(nbuf, sizeof(struct ethhdr));
28939 	skb_put_data(nbuf, buf, len);
28940 	ehdr = skb_push(nbuf, sizeof(struct ethhdr));
28941 	qdf_mem_copy(ehdr->h_dest, dest, ETH_ALEN);
28942 
28943 	if (!src || qdf_is_macaddr_zero((struct qdf_mac_addr *)src))
28944 		qdf_mem_copy(ehdr->h_source, adapter->mac_addr.bytes, ETH_ALEN);
28945 	else
28946 		qdf_mem_copy(ehdr->h_source, src, ETH_ALEN);
28947 
28948 	ehdr->h_proto = proto;
28949 
28950 	nbuf->dev = dev;
28951 	nbuf->protocol = htons(ETH_P_PAE);
28952 	skb_reset_network_header(nbuf);
28953 	skb_reset_mac_header(nbuf);
28954 
28955 	netif_tx_lock(dev);
28956 	skb_set_queue_mapping(nbuf, hdd_wmm_select_queue(dev, nbuf));
28957 	dev->netdev_ops->ndo_start_xmit(nbuf, dev);
28958 	netif_tx_unlock(dev);
28959 
28960 	hdd_exit();
28961 	return 0;
28962 }
28963 
28964 static int _wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
28965 					      struct net_device *dev,
28966 					      const u8 *buf, size_t len,
28967 					      const u8 *src, const u8 *dest,
28968 					      __be16 proto, bool unencrypted)
28969 {
28970 	int errno;
28971 	struct osif_vdev_sync *vdev_sync;
28972 
28973 	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
28974 	if (errno)
28975 		return errno;
28976 
28977 	errno = __wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len, src,
28978 						    dest, proto, unencrypted);
28979 
28980 	osif_vdev_sync_op_stop(vdev_sync);
28981 
28982 	return errno;
28983 }
28984 
28985 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || \
28986 	defined(CFG80211_TX_CONTROL_PORT_LINK_SUPPORT))
28987 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
28988 					     struct net_device *dev,
28989 					     const u8 *buf,
28990 					     size_t len,
28991 					     const u8 *dest, const __be16 proto,
28992 					     bool unencrypted, int link_id,
28993 					     u64 *cookie)
28994 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
28995 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
28996 					     struct net_device *dev,
28997 					     const u8 *buf, size_t len,
28998 					     const u8 *dest, __be16 proto,
28999 					     bool unencrypted, u64 *cookie)
29000 #else
29001 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
29002 					     struct net_device *dev,
29003 					     const u8 *buf, size_t len,
29004 					     const u8 *dest, __be16 proto,
29005 					     bool unencrypted)
29006 #endif
29007 {
29008 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
29009 
29010 	return _wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len,
29011 						  adapter->mac_addr.bytes,
29012 						  dest, proto, unencrypted);
29013 }
29014 
29015 #if defined(CFG80211_CTRL_FRAME_SRC_ADDR_TA_ADDR)
29016 bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
29017 				       u8 *ta_addr,
29018 				       struct sk_buff *skb,
29019 				       bool unencrypted)
29020 {
29021 	return cfg80211_rx_control_port(dev, ta_addr, skb, unencrypted);
29022 }
29023 #else
29024 bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
29025 				       u8 *ta_addr,
29026 				       struct sk_buff *skb,
29027 				       bool unencrypted)
29028 {
29029 	return false;
29030 }
29031 #endif
29032 
29033 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
29034 static int
29035 wlan_hdd_cfg80211_add_intf_link(struct wiphy *wiphy, struct wireless_dev *wdev,
29036 				unsigned int link_id)
29037 {
29038 	return 0;
29039 }
29040 
29041 static void
29042 wlan_hdd_cfg80211_del_intf_link(struct wiphy *wiphy, struct wireless_dev *wdev,
29043 				unsigned int link_id)
29044 {
29045 }
29046 #endif
29047 
29048 #if defined(WLAN_FEATURE_11BE_MLO)
29049 #if defined(WLAN_TID_LINK_MAP_SUPPORT)
29050 #define MAX_T2LM_INFO 2
29051 
29052 static void wlan_hdd_print_t2lm_info(struct cfg80211_mlo_tid_map *map)
29053 {
29054 	int i;
29055 
29056 	hdd_debug("T2LM info send to userspace");
29057 	hdd_debug("default mapping: %d", map->default_map);
29058 	for (i = 0; i < T2LM_MAX_NUM_TIDS; i++)
29059 		hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
29060 			  i, map->t2lmap[i].downlink, map->t2lmap[i].uplink);
29061 }
29062 
29063 static void wlan_hdd_fill_bidir_t2lm(struct wlan_t2lm_info *t2lm,
29064 				     struct tid_link_map *t2lmap)
29065 {
29066 	uint8_t tid;
29067 
29068 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
29069 		t2lmap[tid].downlink = t2lm->ieee_link_map_tid[tid];
29070 		t2lmap[tid].uplink = t2lm->ieee_link_map_tid[tid];
29071 	}
29072 }
29073 
29074 static void wlan_hdd_fill_dldir_t2lm(struct wlan_t2lm_info *t2lm,
29075 				     struct tid_link_map *t2lmap)
29076 {
29077 	uint8_t tid;
29078 
29079 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++)
29080 		t2lmap[tid].downlink = t2lm->ieee_link_map_tid[tid];
29081 }
29082 
29083 static void wlan_hdd_fill_uldir_t2lm(struct wlan_t2lm_info *t2lm,
29084 				     struct tid_link_map *t2lmap)
29085 {
29086 	uint8_t tid;
29087 
29088 	for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++)
29089 		t2lmap[tid].uplink = t2lm->ieee_link_map_tid[tid];
29090 }
29091 
29092 static void wlan_hdd_fill_map(struct wlan_t2lm_info *t2lm,
29093 			      struct cfg80211_mlo_tid_map *map, bool *found)
29094 {
29095 	if (t2lm->direction == WLAN_T2LM_INVALID_DIRECTION)
29096 		return;
29097 
29098 	map->default_map = t2lm->default_link_mapping;
29099 
29100 	switch (t2lm->direction) {
29101 	case WLAN_T2LM_BIDI_DIRECTION:
29102 		wlan_hdd_fill_bidir_t2lm(t2lm, map->t2lmap);
29103 		*found = true;
29104 		break;
29105 	case WLAN_T2LM_DL_DIRECTION:
29106 		wlan_hdd_fill_dldir_t2lm(t2lm, map->t2lmap);
29107 		*found = true;
29108 		break;
29109 	case WLAN_T2LM_UL_DIRECTION:
29110 		wlan_hdd_fill_uldir_t2lm(t2lm, map->t2lmap);
29111 		*found = true;
29112 		break;
29113 	default:
29114 		return;
29115 	}
29116 }
29117 
29118 static int wlan_hdd_fill_t2lm_response(struct wlan_t2lm_info *t2lm,
29119 				       struct cfg80211_mlo_tid_map *map)
29120 {
29121 	uint8_t i;
29122 	bool found = false;
29123 
29124 	for (i = 0; i < MAX_T2LM_INFO; i++)
29125 		wlan_hdd_fill_map(&t2lm[i], map, &found);
29126 
29127 	if (!found) {
29128 		hdd_err("T2LM info not found");
29129 		return -EINVAL;
29130 	}
29131 
29132 	wlan_hdd_print_t2lm_info(map);
29133 
29134 	return 0;
29135 }
29136 
29137 static int
29138 __wlan_hdd_cfg80211_get_t2lm_mapping_status(struct wiphy *wiphy,
29139 					    struct net_device *net_dev,
29140 					    struct cfg80211_mlo_tid_map *map)
29141 {
29142 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(net_dev);
29143 	struct wlan_objmgr_vdev *vdev;
29144 	struct wlan_t2lm_info *t2lm = NULL;
29145 	int ret, i;
29146 
29147 	hdd_enter();
29148 
29149 	if (hdd_validate_adapter(adapter))
29150 		return -EINVAL;
29151 
29152 	vdev = hdd_objmgr_get_vdev_by_user(adapter->deflink, WLAN_OSIF_ID);
29153 	if (!vdev) {
29154 		hdd_err("Vdev is null return");
29155 		return -EINVAL;
29156 	}
29157 
29158 	if (!wlan_cm_is_vdev_connected(vdev)) {
29159 		hdd_err("Not associated!, vdev %d", wlan_vdev_get_id(vdev));
29160 		ret = -EAGAIN;
29161 		goto vdev_release;
29162 	}
29163 
29164 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) {
29165 		hdd_err("failed due to non-ML connection");
29166 		ret = -EINVAL;
29167 		goto vdev_release;
29168 	}
29169 
29170 	t2lm = qdf_mem_malloc(sizeof(*t2lm) * MAX_T2LM_INFO);
29171 	if (!t2lm) {
29172 		hdd_err("mem alloc failed for t2lm");
29173 		ret = -ENOMEM;
29174 		goto vdev_release;
29175 	}
29176 
29177 	for (i = 0; i < MAX_T2LM_INFO; i++)
29178 		t2lm[i].direction = WLAN_T2LM_INVALID_DIRECTION;
29179 
29180 	ret = wlan_get_t2lm_mapping_status(vdev, t2lm);
29181 	if (ret != 0)
29182 		goto t2lm_free;
29183 
29184 	ret = wlan_hdd_fill_t2lm_response(t2lm, map);
29185 
29186 t2lm_free:
29187 	qdf_mem_free(t2lm);
29188 vdev_release:
29189 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
29190 
29191 	hdd_exit();
29192 
29193 	return ret;
29194 }
29195 
29196 static int
29197 wlan_hdd_cfg80211_get_t2lm_mapping_status(struct wiphy *wiphy,
29198 					  struct net_device *net_dev,
29199 					  struct cfg80211_mlo_tid_map *map)
29200 {
29201 	int errno;
29202 	struct osif_vdev_sync *vdev_sync;
29203 
29204 	errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
29205 	if (errno)
29206 		return errno;
29207 
29208 	errno = __wlan_hdd_cfg80211_get_t2lm_mapping_status(wiphy, net_dev, map);
29209 
29210 	osif_vdev_sync_op_stop(vdev_sync);
29211 
29212 	return errno;
29213 }
29214 
29215 QDF_STATUS hdd_tid_to_link_map(struct wlan_objmgr_vdev *vdev,
29216 			       struct wlan_t2lm_info *t2lm,
29217 			       struct net_device *dev)
29218 {
29219 	struct cfg80211_mlo_tid_map map;
29220 	bool found = false;
29221 
29222 	qdf_mem_zero(&map, sizeof(map));
29223 	wlan_hdd_fill_map(t2lm, &map, &found);
29224 	if (!found) {
29225 		hdd_debug("Failed to get t2lm info");
29226 		return QDF_STATUS_E_FAILURE;
29227 	}
29228 
29229 	wlan_hdd_print_t2lm_info(&map);
29230 	cfg80211_tid_to_link_map_change(dev, &map);
29231 	return QDF_STATUS_SUCCESS;
29232 }
29233 
29234 #else
29235 static void wlan_hdd_print_vendor_t2lm_info(struct wlan_t2lm_info *t2lm)
29236 {
29237 	int tid, value = 0;
29238 
29239 	hdd_debug("default mapping: %d", t2lm->default_link_mapping);
29240 
29241 	if (t2lm->direction == WLAN_T2LM_INVALID_DIRECTION)
29242 		return;
29243 
29244 	switch (t2lm->direction) {
29245 	case WLAN_T2LM_BIDI_DIRECTION:
29246 		for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
29247 			hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
29248 				  tid, t2lm->ieee_link_map_tid[tid],
29249 				  t2lm->ieee_link_map_tid[tid]);
29250 		}
29251 		break;
29252 	case WLAN_T2LM_DL_DIRECTION:
29253 		for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
29254 			/* Keep uplink info as 0 for downlink direction */
29255 			hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
29256 				  tid, t2lm->ieee_link_map_tid[tid], value);
29257 		}
29258 		break;
29259 	case WLAN_T2LM_UL_DIRECTION:
29260 		for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) {
29261 			/* Keep downlinklink info as 0 for downlink direction */
29262 			hdd_debug("TID[%d]: Downlink: %d Uplink: %d",
29263 				  tid, value, t2lm->ieee_link_map_tid[tid]);
29264 		}
29265 		break;
29266 	default:
29267 		return;
29268 	}
29269 }
29270 
29271 QDF_STATUS hdd_tid_to_link_map(struct wlan_objmgr_vdev *vdev,
29272 			       struct wlan_t2lm_info *t2lm,
29273 			       struct net_device *dev)
29274 {
29275 	uint8_t ret;
29276 
29277 	wlan_hdd_print_vendor_t2lm_info(t2lm);
29278 	ret = wlan_hdd_send_t2lm_event(vdev, t2lm);
29279 	if (QDF_IS_STATUS_ERROR(ret)) {
29280 		hdd_debug("failed to send t2lm info to userspace");
29281 		return QDF_STATUS_E_FAILURE;
29282 	}
29283 	return QDF_STATUS_SUCCESS;
29284 }
29285 #endif
29286 
29287 QDF_STATUS hdd_mlo_dev_t2lm_notify_link_update(struct wlan_objmgr_vdev *vdev,
29288 					       struct wlan_t2lm_info *t2lm)
29289 {
29290 	struct wlan_hdd_link_info *link_info;
29291 	struct net_device *dev;
29292 	uint8_t ret;
29293 
29294 	link_info = wlan_hdd_get_link_info_from_objmgr(vdev);
29295 	if (!link_info) {
29296 		hdd_err("Invalid VDEV");
29297 		return QDF_STATUS_E_FAILURE;
29298 	}
29299 
29300 	dev = link_info->adapter->dev;
29301 	hdd_enter_dev(dev);
29302 
29303 	ret = hdd_tid_to_link_map(vdev, t2lm, dev);
29304 	if (QDF_IS_STATUS_ERROR(ret)) {
29305 		hdd_debug("tid to link map change failed ");
29306 		return QDF_STATUS_E_FAILURE;
29307 	}
29308 
29309 	hdd_exit();
29310 
29311 	return QDF_STATUS_SUCCESS;
29312 }
29313 #endif
29314 
29315 static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
29316 	.add_virtual_intf = wlan_hdd_add_virtual_intf,
29317 	.del_virtual_intf = wlan_hdd_del_virtual_intf,
29318 	.change_virtual_intf = wlan_hdd_cfg80211_change_iface,
29319 	.change_station = wlan_hdd_change_station,
29320 	.start_ap = wlan_hdd_cfg80211_start_ap,
29321 	.change_beacon = wlan_hdd_cfg80211_change_beacon,
29322 	.stop_ap = wlan_hdd_cfg80211_stop_ap,
29323 	.change_bss = wlan_hdd_cfg80211_change_bss,
29324 	.add_key = wlan_hdd_cfg80211_add_key,
29325 	.get_key = wlan_hdd_cfg80211_get_key,
29326 	.del_key = wlan_hdd_cfg80211_del_key,
29327 	.set_default_key = wlan_hdd_cfg80211_set_default_key,
29328 	.scan = wlan_hdd_cfg80211_scan,
29329 	.connect = wlan_hdd_cfg80211_connect,
29330 	.disconnect = wlan_hdd_cfg80211_disconnect,
29331 	.set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
29332 	.set_tx_power = wlan_hdd_cfg80211_set_txpower,
29333 	.get_tx_power = wlan_hdd_cfg80211_get_txpower,
29334 	.remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
29335 	.cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
29336 	.mgmt_tx = wlan_hdd_mgmt_tx,
29337 	.mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
29338 	.set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
29339 #if defined (CFG80211_BIGTK_CONFIGURATION_SUPPORT) || \
29340 	    (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
29341 	.set_default_beacon_key = wlan_hdd_cfg80211_set_default_beacon_key,
29342 #endif
29343 	.set_txq_params = wlan_hdd_set_txq_params,
29344 	.dump_station = wlan_hdd_cfg80211_dump_station,
29345 	.get_station = wlan_hdd_cfg80211_get_station,
29346 	.set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
29347 	.del_station = wlan_hdd_cfg80211_del_station,
29348 	.add_station = wlan_hdd_cfg80211_add_station,
29349 	.set_pmksa = wlan_hdd_cfg80211_set_pmksa,
29350 	.del_pmksa = wlan_hdd_cfg80211_del_pmksa,
29351 	.flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
29352 #if defined(KERNEL_SUPPORT_11R_CFG80211)
29353 	.update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
29354 #endif
29355 #if defined(CFG80211_EXTERNAL_DH_UPDATE_SUPPORT) || \
29356 (LINUX_VERSION_CODE > KERNEL_VERSION(5, 2, 0))
29357 	.update_owe_info = wlan_hdd_cfg80211_update_owe_info,
29358 #endif
29359 #ifdef FEATURE_WLAN_TDLS
29360 	.tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
29361 	.tdls_oper = wlan_hdd_cfg80211_tdls_oper,
29362 #endif
29363 #ifdef WLAN_FEATURE_GTK_OFFLOAD
29364 	.set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
29365 #endif /* WLAN_FEATURE_GTK_OFFLOAD */
29366 #ifdef FEATURE_WLAN_SCAN_PNO
29367 	.sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
29368 	.sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
29369 #endif /*FEATURE_WLAN_SCAN_PNO */
29370 	.resume = wlan_hdd_cfg80211_resume_wlan,
29371 	.suspend = wlan_hdd_cfg80211_suspend_wlan,
29372 	.set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
29373 #ifdef WLAN_NL80211_TESTMODE
29374 	.testmode_cmd = wlan_hdd_cfg80211_testmode,
29375 #endif
29376 #ifdef QCA_HT_2040_COEX
29377 	.set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
29378 #endif
29379 	.dump_survey = wlan_hdd_cfg80211_dump_survey,
29380 #ifdef CHANNEL_SWITCH_SUPPORTED
29381 	.channel_switch = wlan_hdd_cfg80211_channel_switch,
29382 #endif
29383 #ifdef FEATURE_MONITOR_MODE_SUPPORT
29384 	.set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
29385 #endif
29386 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
29387 	defined(CFG80211_ABORT_SCAN)
29388 	.abort_scan = wlan_hdd_cfg80211_abort_scan,
29389 #endif
29390 #if defined(CFG80211_UPDATE_CONNECT_PARAMS) || \
29391 	(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
29392 	.update_connect_params = wlan_hdd_cfg80211_update_connect_params,
29393 #endif
29394 #if defined(WLAN_FEATURE_SAE) && \
29395 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
29396 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
29397 	.external_auth = wlan_hdd_cfg80211_external_auth,
29398 #endif
29399 #if defined(WLAN_FEATURE_NAN) && \
29400 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
29401 	.start_nan = wlan_hdd_cfg80211_start_nan,
29402 	.stop_nan = wlan_hdd_cfg80211_stop_nan,
29403 	.add_nan_func = wlan_hdd_cfg80211_add_nan_func,
29404 	.del_nan_func = wlan_hdd_cfg80211_del_nan_func,
29405 	.nan_change_conf = wlan_hdd_cfg80211_nan_change_conf,
29406 #endif
29407 	.set_antenna = wlan_hdd_cfg80211_set_chainmask,
29408 	.get_antenna = wlan_hdd_cfg80211_get_chainmask,
29409 	.get_channel = wlan_hdd_cfg80211_get_channel,
29410 	.set_bitrate_mask = wlan_hdd_cfg80211_set_bitrate_mask,
29411 	.tx_control_port = wlan_hdd_cfg80211_tx_control_port,
29412 #ifdef CFG80211_SINGLE_NETDEV_MULTI_LINK_SUPPORT
29413 	.add_intf_link = wlan_hdd_cfg80211_add_intf_link,
29414 	.del_intf_link = wlan_hdd_cfg80211_del_intf_link,
29415 #endif
29416 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_TID_LINK_MAP_SUPPORT)
29417 	.get_link_tid_map_status = wlan_hdd_cfg80211_get_t2lm_mapping_status,
29418 #endif
29419 };
29420